2016-11-14 1 views
0

Configuration: Il y a une classe classA, et une classe classB qui utilise classA. Malheureusement, lors de la programmation classB, je ne sais pas si classA aura un certain membre someMember ou non. En fonction de cela, une fonction membre someFunction dans classB doit être implémentée soit dans l'un ou l'autre sens. Comme l'one-way utilise someMember, il est important que cette instance de fonction n'est pas compilée dans le cas someMember n'est pas un membre de classA.C++ 98: Fournir différentes implémentations de fonction, en fonction de l'existance d'un membre

Question: En dehors des macros/définit, quelle est la meilleure solution pour cela en C++ 98?

MWE:

class classA 
{ 
public: 
    // c'tor 
    classA() 
    { 
     //someMember = 3; 
    }; 
    // does not have the member "someMember" 
    //int someMember; 
}; 

class classB 
{ 
public: 
    // only compile this function if "someMember" is a member of classB 
    int someFunction(classA a) 
    { 
     return a.someMember; 
    } 
    // ...and compile this one otherwise 
    int someFunction(classA a) 
    { 
     return 2; 
    } 
}; 

// --- just to have an MWE: --- 
#include<iostream> 
int main() 
{ 
    classA a; 
    classB b; 
    cout << b.someFunction(a); 
    return 0; 
} 
+1

"Je ne sais pas si classA aura un certain membre ou non" n que 'classB' est un template dans votre code réel et' classA' est un paramètre template? – TartanLlama

+0

Non, cela signifie qu'il existe différentes versions de 'classA', et selon la version de' classA' que j'utilise, il y aura 'someMember' ou pas. C'est un problème de compatibilité et de configuration. 'classA' vit dans un composant logiciel différent qui pourrait être combiné dans différentes versions avec mon composant logiciel (' classB'). – matheburg

+0

https://fr.wikibooks.org/wiki/More_C%2B%2B_Idioms/Member_Detector – acraig5075

Répondre

2

Comme votre question est taggés templates Je suppose que votre classB peut effectivement être un modèle de classe ou au moins il peut utiliser un ... Si tel est le cas, vous pouvez appliquer SFINAE par exemple en utilisant la solution suivante:

#include <iostream> 
#include <type_traits> 

class classA 
{ 
public: 
    // c'tor 
    classA() 
    { 
     someMember = 3; 
    }; 
    // does not have the member "someMember" 
    int someMember; 
}; 

template<class T, class = void> 
class classB_impl 
{ 
public: 
    // ...and compile this one otherwise 
    int someFunction(T) 
    { 
     return 2; 
    } 
}; 

template <class T> 
class classB_impl<T, decltype(std::declval<T>().someMember, void())> { 
public: 
    // only compile this function if "someMember" is a member of classB 
    int someFunction(T a) 
    { 
     return a.someMember; 
    } 
}; 

using classB = classB_impl<classA>; 

int main() { 
    classB b; 
    std::cout << b.someFunction(classA{}) << std::endl; 
} 

[live demo]


Dans ce cas (si vous utilisez C++ 98), vous pouvez obtenir plus de chance d'essayer d'utiliser trait supplémentaire par exemple:

#include <iostream> 

class classA 
{ 
public: 
    // c'tor 
    classA() 
    { 
     someMember = 3; 
    }; 
    // does not have the member "someMember" 
    int someMember; 
}; 

template <class T, int T::*V = &T::someMember> 
struct someMemberTrait { 
    typedef void type; 
}; 

template<class T, class = void> 
class classB_impl 
{ 
public: 
    // ...and compile this one otherwise 
    int someFunction(T) 
    { 
     return 2; 
    } 
}; 

template <class T> 
class classB_impl<T, typename someMemberTrait<T>::type> { 
public: 
    // only compile this function if "someMember" is a member of classB 
    int someFunction(T a) 
    { 
     return a.someMember; 
    } 
}; 

typedef classB_impl<classA> classB; 

int main() { 
    classB b; 
    std::cout << b.someFunction(classA()) << std::endl; 
} 

[live demo]

+0

Merci pour votre réponse rapide. Malheureusement, vous ne le croirez pas, nous utilisons toujours la norme C++ 98. Pour autant que je sache, 'decltype' n'est pas disponible ici. – matheburg

+1

@matheburg voir mon édition –

+0

Merci, cela fonctionne! – matheburg