4

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 ?

Community
  • 1
  • 1
jnnnnn
  • 3,889
  • 32
  • 37
  • 2
    If you are going to be the only person who maintains it for the rest of its life :) – Michael Dorgan Sep 14 '11 at 23:30
  • I am almost certain this will only cause more headaches than it solves. I can't think of a way to do this that doesn't involve changes to your interface that imply you should re-think the design you've outlined here. – tenfour Sep 14 '11 at 23:36
  • If the target class, in this case `CHandler`, does not have a public `m_pScience` member, the compiler will let you know when the template is instantiated. – Thomas Matthews Sep 14 '11 at 23:53
  • This is almost, but not quite exactly the same as: http://stackoverflow.com/questions/1005476/how-to-detect-whether-there-is-a-specific-member-variable-in-class – Omnifarious Sep 15 '11 at 00:57

2 Answers2

5

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).

Community
  • 1
  • 1
MSN
  • 53,214
  • 7
  • 75
  • 105
1

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.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182