Reputation: 2180
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
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;
}
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;
}
Upvotes: 2