Reputation: 4353
Edit: Sorry, this question is a duplicate. Original: SFINAE to check for inherited member functions
I have a templated function (in a class used for testing):
template <class CHandler>
void InitHandler(CHandler &handler)
{
handler.setId(0);
handler.SetCache(m_pCache.get());
handler.m_pScience = m_pScience;
}
However it is possible that this function will may be called with a template argument that doesn't have an m_pScience member.
Can I use template metaprogramming to only set this member if it exists ?
Upvotes: 4
Views: 997
Reputation: 54604
Reimagining this answer: How to detect whether there is a specific member variable in class?:
template<typename T> struct Hasm_pScience
{
struct Fallback { int m_pScience; }; // introduce member name "m_pScience"
struct Derived : T, Fallback { };
template<typename C, C> struct ChT;
template<typename C> static char (&f(ChT<int Fallback::*, &C::m_pScience>*))[1];
template<typename C> static char (&f(...))[2];
static bool const value = sizeof(f<Derived>(0)) == 2;
};
struct A { float m_pScience; };
struct B { int X; };
int main(int argc, _TCHAR* argv[])
{
std::cout << Hasm_pScience<A>::value << std::endl; // 1
std::cout << Hasm_pScience<B>::value << std::endl; // 0
return 0;
}
The general principle to google for is SFINAE (substitution failure is not an error).
Upvotes: 5
Reputation: 47533
Usually, when you need a certain member in a template, you should force the users of the template to implement it, even if it serves no purpose for them. Common examples are stl set
and map
where you need to define an operator <
.
There are many (proper) ways you can do what you want, but they all involve you requiring the user of the template to have a certain member variable or function.
You could also have two templates, one for the ones having m_pScience
and one for those who don't, but I don't recommend this. This way, you'd have to make sure always that the code between the two templates are consistent.
Upvotes: 1