C++98:根据成员的存在提供不同的函数实现

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

设置: 有一个 class classA,还有一个 class classB 使用 classA.不幸的是,在编程classB时,我不知道classA是否会有某个成员someMember。取决于此,classB 中的成员函数 someFunction 应以一种或另一种方式实现。由于一种方法是使用 someMember,因此 重要的是在 someMember 不是 classA 的成员的情况下不编译此函数实例.

问题: 除了 macros/defines,在 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;
}

因为你的问题被标记为 templates 我假设你的 classB 实际上可以是一个 class 模板或者至少它可以使用一个...如果是这种情况你可以应用 SFINAE 例如使用以下解决方案:

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


在这种情况下(如果您使用的是 c++98),尝试使用其他特征可能会更幸运,例如:

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