5

I have a class A that has a template parameter T. There are use cases where the class T offers a function func1() and there are use cases where T doesn't offer it. A function f() in A should call func1(), iff it exists. I think this should be possible with boost mpl, but I don't know how. Here some pseudo code:

template<class T>
class A
{
    void f(T param)
    {
        if(T::func1 is an existing function)
            param.func1();
    }
};

Even better would be an else-case:

template<class T>
class A
{
    void f(T param)
    {
        if(T::func1 is an existing function)
            param.func1();
        else
            cout << "func1 doesn't exist" << endl;
    }
};
Nicol Bolas
  • 378,677
  • 53
  • 635
  • 829
Heinzi
  • 4,834
  • 3
  • 31
  • 57
  • 2
    Even if you manage to find a proper condition that code won't compile. Both branches of the if must compile, and if the function doesn't exist, the true branch will not compile. – R. Martinho Fernandes Oct 07 '11 at 11:58
  • With template specialisation it isn't necessary that both parts compile. Somehow I would have to call a template function with parameter T and this function has a differend behaviour when T offers or doesn't offer func1(). I am sure boost mpl offers something for this use case. I just don't know how to use it. – Heinzi Oct 07 '11 at 12:01

1 Answers1

7

Boost.MPL doesn't deal with that as it's strictly for TMP and you can't call members in TMP. Boost.Fusion and Boost.TypeTraits don't have anything either; I thought one of them would but apparently I'm misremembering.

Here and here are some solutions on how to write a trait to detect a member in C++03. Once you have such a trait (I'll call it has_func1_member), you can use it for SFINAE:

template<typename T>
typename boost::enable_if<has_func1_member<T> >::type
maybe_call(T& t)
{ t.func1(); }

template<typename T>
typename boost::disable_if<has_func1_member<T> >::type
maybe_call(T&)
{
    // handle missing member case
}

// your example code would then do:
maybe_call(param);

Note that with C++11 it's easier to write the trait in the first place, although it's still somewhat arcane.

Community
  • 1
  • 1
Luc Danton
  • 33,152
  • 5
  • 66
  • 110
  • Would you actually have to write it yourself? Doesn't is_member_function_pointer do the trick? http://en.cppreference.com/w/cpp/types/is_member_function_pointer or in Boost: http://www.boost.org/doc/libs/1_51_0/libs/type_traits/doc/html/boost_typetraits/reference/is_member_function_pointer.html – Gurgeh Nov 05 '12 at 09:41
  • @Gurgeh In C++03 it doesn't help. In C++11 you may be able to write something that works but it'll likely fail with overloaded member functions (will report a false negative) and there are easier ways to do it without that drawback. – Luc Danton Nov 05 '12 at 10:01