2017-03-02 2 views
3

Betrachten wir ein kleines Standalone-Betrieb Fall, in dem ich feststellen möchten, ob ein Typ eine vollständige oder unvollständige Verwendunggcc 6.1 std :: result_of Kompilierungsfehler

#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; 
} 

Das mit gcc 4.9.3 mit --std=c++11 Flagge fein kompiliert. Doch mit gcc 6.1 und --std=c++11 es produziert ein compilation error als

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(); 

Was bin ich hier? Was könnte eine mögliche Arbeit sein?

+0

Sieht aus wie eine g ++ -Regression – Arunmu

+0

@Arunmu Sollte g ++ 'operator() (...)' dann? Es versucht, eine Kopie eines unvollständigen Typs –

+0

zu erstellen. Haben Sie es ohne anonymen 'Namespace' versucht, d. H. Verwenden Sie stattdessen einen benannten. – user3405291

Antwort

0

Seit C++ 14 result_of :: Typ existiert nicht, wenn T nicht aufrufbar ist.

In Ihrem Fall hat Struktur FooIncomplete nichts zu nennen.

+0

OP versucht, 'foo :: operator()', nicht 'FooIncomplete' aufzurufen –

0

mit so etwas wie C++ 20- 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 >; 

wir bekommen ein Merkmal is_complete die wahr ist, genau dann, wenn wir sizeof-T anwenden können.

Seien Sie vorsichtig damit, denn im Gegensatz zu den meisten Features kann sich die Vollständigkeit eines Typs zwischen Kompilierungseinheiten und sogar an verschiedenen Stellen in derselben Einheit ändern. Und C++ nicht wie es, wenn der Typ some_template<some_args...> an verschiedenen Stellen in Ihrem Programm ändert.

Live example.

Verwandte Themen