matheburg matheburg - 20 days ago 6
C++ Question

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;
}

Answer

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]

Comments