2012-06-30 4 views
5

mi ha questa funzione membro di test:SFINAE funzione membro questione di prova dell'esistenza

template <typename T> 
struct has_member { 
    template <typename U> static true_type f(decltype(declval<U>().member()) *); 
    template <typename> static false_type f(...); 
    static const bool value = decltype(f<T>(0))::value; 
}; 

Si restituisce vero quando esiste una funzione di membro con un dato nome, nel caso in cui la funzione ha un sovraccarico che non tiene argomenti. Per tali funzioni e nel caso di contenitori STL, funziona correttamente eccetto per le funzioni di accesso agli elementi (fronte, retro ecc.), Dove invariabilmente viene valutato come falso.

Perché è quello? Ho mingw g ++ 4.7.

+0

Si passa alla guida di tipo ritorno di ritorno? 'auto f (U * p) -> decltype (p-> membro(), true_type());' – Xeo

risposta

6

Ecco perché queste funzioni restituiscono riferimenti e si dichiara un puntatore al valore restituito, ovvero un puntatore a un riferimento e ciò è impossibile.

La soluzione rapida sarebbe:

template <typename U> static true_type 
     f(typename remove_reference< decltype(declval<U>().member()) >::type *); 

PS: Questo tipo di errori può essere (relativamente) facile da risolvere se si forza il compilatore per dare un errore quando lo SFINAE non riesce e si pensa che non dovrebbe.

Voglio dire, nel codice, basta commentare lo false_type e vedere gli errori dal compilatore quando true_type è l'unica opzione. Tra un buch di righe senza senso, c'è il seguente:

test.cpp:9:50: error: forming pointer to reference type 
    ‘__gnu_cxx::__alloc_traits<std::allocator<int> >::value_type& {aka int&}’ 
+0

Grazie, ha funzionato. Penso di aver trovato un modo per farlo senza rimuovere il riferimento: includo "typename Check = decltype (declval () .front()" come secondo argomento template, e f, invece, far passare un puntatore char. –

+0

@ AndrásKovács - Ancora meglio in questo modo. – rodrigo