matheburg
matheburg

Reputation: 2180

C++98: Provide different function implementations, depending on the existance of a member

Setup: There is a class classA, and a class classB that is using classA. Unfortunately, when programming classB, I do not know whether classA will have a certain member someMember or not. Depending on that, a member function someFunction in classB shall be implemented either the one or the other way. As the one way is using someMember, it is important that this function instance is not compiled in the case someMember is not a member of classA.

Question: Apart from macros/defines, what is the best solution for that in 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;
}

Upvotes: 0

Views: 76

Answers (1)

W.F.
W.F.

Reputation: 13988

As your question is tagged templates I assume your classB can actually be a class template or at least it can use one... If this is the case you could apply SFINAE e.g. using following solution:

#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]


In this case (if you are using c++98) you might get more lucky trying to use additional trait e.g.:

#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]

Upvotes: 2

Related Questions