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;
}
在这种情况下(如果您使用的是 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;
}
设置: 有一个 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;
}
在这种情况下(如果您使用的是 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;
}