2012-08-13 18 views
10

Ho scritto il codice seguente per provare a rilevare se un tipo ha una variabile membro statica. Sfortunatamente, sta sempre tornando che la variabile non esiste.controllo sfina per membro statico utilizzando decltype

Qualcuno potrebbe dirmi dove sto andando male? Sto usando g ++ 4.7.1.

#include <iostream> 
#include <utility> 
#include <type_traits> 

using namespace std; 

template <class T>             
class has_is_baz               
{                 
    template<class U, 
      typename std::enable_if<std::is_same<bool, decltype(U::is_baz)>::value>::type...>      
     static std::true_type check(int);       
    template <class>             
     static std::false_type check(...);       
public:                
    static constexpr bool value = decltype(check<T>(0))::value;  
}; 

struct foo { }; 

struct bar 
{ 
    static constexpr bool is_baz = true; 
}; 

int main() 
{ 
    cout << has_is_baz<foo>::value << '\n'; 
    cout << has_is_baz<bar>::value << '\n'; 
} 

risposta

8

Il problema principale era che:

std::is_same<bool, decltype(bar::is_baz)>::value == false 

Allora la vostra SFINAE stava venendo a mancare sempre. Ho ri-scritto la has_is_baz tratto e funziona ora:

#include <iostream> 
#include <utility> 
#include <type_traits> 

using namespace std; 

template <class T>             
class has_is_baz               
{  
    template<class U, class = typename std::enable_if<!std::is_member_pointer<decltype(&U::is_baz)>::value>::type> 
     static std::true_type check(int); 
    template <class> 
     static std::false_type check(...); 
public: 
    static constexpr bool value = decltype(check<T>(0))::value; 
}; 

struct foo { }; 

struct bar 
{ 
    static constexpr bool is_baz = true; 
}; 

struct not_static { 
    bool is_baz; 
}; 

int main() 
{ 
    cout << has_is_baz<foo>::value << '\n'; 
    cout << has_is_baz<bar>::value << '\n'; 
    cout << has_is_baz<not_static>::value << '\n'; 
} 

Demo here.

Modifica: Ho corretto il tipo di carattere. Come indicato da @litb, stava rilevando membri statici e membri non statici.

+0

Ciò non richiede che 'U :: is_baz' sia statico. Una 'struct A {bool is_baz; }; 'funzionerà altrettanto bene. –

+0

@ JohannesSchaub-litb hai ragione. Sembra che funzioni ora. – mfontanini

5

Il problema nel codice è che un oggetto constexpr è implicitamente const, il che significa che il test per lo stesso tipo dovrebbe essere:

std::is_same<const bool, decltype(U::is_baz)>::value 

Questo è specificato nella norma in §7.1.5 [dcl. constexpr]/9

Uno specificatore di constexpr utilizzato in una dichiarazione oggetto dichiara l'oggetto come const. [...]

Problemi correlati