2016-04-20 2 views
0

après avoir griffonné par plusieurs fils comme celui-ciC++ enable_if is_member_function_pointer appel en fonction de l'existence de la fonction membre

SFINAE for detecting existence of non-member template function

sans trouver une solution, je poste ma question ici. Pour une classe de logger minuscule, je veux surveiller la quantité de données enregistrées en utilisant l'opérateur < <. Quand, par exemple, une chaîne est passe ou un tableau ayant la fonction membre .size(), je veux ajouter size() nombre d'octets à cette valeur, sizeof (...) sinon. Comment puis-je (en utilisant VS 2010, qui a un support C++ 11 très clairsemé) utiliser std :: enable_if et std :: is_member_function_pointer pour atteindre mon objectif? Comment puis-je, par exemple, définir une fonction getSize() qui fonctionne comme voulu?

Le code ci-dessous indique ce que je veux, mais je suppose que je ne peux pas définir getSize deux fois ...

Merci beaucoup pour l'aide!

template<typename T, 
typename = typename std::enable_if<std::is_member_function_pointer<decltype(&T::size)>::value> 
> 
size_t getSize(const T &p_rObj) 
{ 
    return p_rObj.size(); 
} 

template<typename T, 
    typename = typename std::enable_if<!std::is_member_function_pointer<decltype(&T::size)>::value> 
> 
size_t getSize(const T &p_rObj) 
{ 
    return sizeof(p_rObj); 
} 

Addendumg/Edit: Ce qui suit soit ne fonctionne pas avec VS 2010, qui attend alors chaque appel de getSize (...) d'avoir deux paramètres ...

template<typename T> 
size_t getSize(std::enable_if<std::is_member_function_pointer<decltype(&T::size)>::value>, const T &p_rObj) 
{ 
    return p_rObj.size(); 
} 

template<typename T> 
size_t getSize(std::enable_if<!std::is_member_function_pointer<decltype(&T::size)>::value>, const T &p_rObj) 
{ 
    return sizeof(p_rObj); 
} 
+0

Ah, je suppose que j'ai trouvé la solution moi-même: Utilisation de std :: enable_if en tant que paramètre de fonction. Cependant, Herb Sutter déconseille fortement cela, et je suis impatient de recevoir des suggestions alternatives! – gilgamash

Répondre

0

Vous définir deux fois

template<typename T, typename> size_t getSize(const T &p_rObj); 

et vous oubliez ::type et vos traits n'est pas compatible SFINAE

Vous devez utiliser std::enable_if dans le type de retour, l'argument de modèle ou un argument régulier:

template<typename T> 
typename std::enable_if<has_size<T>::value, std::size_t>::type 
getSize(const T &p_rObj); 

ou

template<typename T, 
typename std::enable_if<has_size<T>::value>::type* = nullptr> 
std::size_t getSize(const T &p_rObj); 

ou

template<typename T> 
std::size_t getSize(const T &p_rObj, 
        typename std::enable_if<has_size<T>::value>::type* = nullptr); 

Demo

+0

Oui, je sais que je l'ai défini deux fois (voir mon propre commentaire ci-dessus). Et comment suggérez-vous de retourner size() ou sizeof()? Merci d'avance ... – gilgamash

+0

Je veux dire changer * argument par défaut * ne compte pas comme ** nouvelle ** fonction. – Jarod42

+0

Non has_size here ... et no :: type (ne fait pas partie de l'implémentation de VS 2010 TR1) – gilgamash