2017-03-02 3 views
3

Considérons un petit cas d'utilisation autonome dans laquelle je veux déterminer si un type est complet ou incomplet en utilisantgcc 6.1 std :: erreur de compilation result_of

#include <type_traits> 
namespace { 

struct foo { 
    template<class T, std::size_t = sizeof(T)> 
    std::false_type operator()(T&); 
    std::true_type operator()(...); 
}; 

struct FooIncomplete; 
} 


int main() { 
    std::result_of<foo(FooIncomplete&)>::type(); 

    return 0; 
} 

Cette compile très bien avec gcc 4.9.3 avec --std=c++11 drapeau. Cependant, avec gcc 6.1 et --std=c++11 il produit un compilation error comme

main.cpp: In function 'int main()': 
main.cpp:17:5: error: 'type' is not a member of 'std::result_of<{anonymous}::foo({anonymous}::FooIncomplete&)>' 
    std::result_of<foo(FooIncomplete&)>::type(); 

Qu'est-ce que je manque ici? Quel pourrait être un travail possible?

+0

Ressemble à une régression g ++ – Arunmu

+0

@Arunmu G ++ devrait-il choisir 'operator() (...)' alors? Il tente de faire une copie d'un type incomplet. –

+0

L'avez-vous essayé sans "namespace" anonyme, c'est-à-dire en utilisant un nom nommé à la place. – user3405291

Répondre

0

Puisque C++ 14 result_of :: type n'existe pas si T n'est pas appelable.

Dans votre cas, struct FooIncomplete n'a rien à appeler.

+0

OP essaie d'invoquer 'foo :: operator()', pas 'FooIncomplete' –

0

En utilisant quelque chose comme C++ 20 de is_detected:

namespace details { 
    template<template<class...>class Z, class, class...Ts> 
struct can_apply:std::false_type{}; 
    template<class...>struct voider{using type=void;}; 
    template<class...Ts>using void_t = typename voider<Ts...>::type; 

    template<template<class...>class Z, class...Ts> 
    struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{}; 
} 
template<template<class...>class Z, class...Ts> 
using can_apply=typename details::can_apply<Z,void,Ts...>::type; 

template<class T> 
using size_of = std::integral_constant<std::size_t, sizeof(T)>; 

template<class T> 
using is_complete = can_apply< size_of, T >; 

nous obtenons un trait is_complete qui est vrai ssi nous pouvons appliquer sizeof-T.

Soyez prudent avec cela, car contrairement à la plupart des fonctionnalités, l'intégralité d'un type peut changer entre les unités de compilation et même à différents endroits dans la même unité. Et C++ ne comme il lorsque le type some_template<some_args...> change à différents endroits dans votre programme.

Live example.