Boost MPL: Call a (member) function only if it exists
Asked Answered
O

1

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;
    }
};
Orest answered 7/10, 2011 at 11:43 Comment(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.Apologetic
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.Orest
O
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.

Obligation answered 7/10, 2011 at 12:23 Comment(2)
Would you actually have to write it yourself? Doesn't is_member_function_pointer do the trick? en.cppreference.com/w/cpp/types/is_member_function_pointer or in Boost: boost.org/doc/libs/1_51_0/libs/type_traits/doc/html/…Heartily
@Heartily 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.Obligation

© 2022 - 2024 — McMap. All rights reserved.