是否可以编写一个模板,根据类中是否定义了某个成员函数来更改行为?
下面是我想要写的一个简单的例子:
template<class T>
std::string optionalToString(T* obj)
{
if (FUNCTION_EXISTS(T->toString))
return obj->toString();
else
return "toString not defined";
}所以,如果class T定义了toString(),那么它就会使用它;否则,它就不会使用它。
发布于 2020-09-10 13:26:41
我知道这个问题由来已久,但我认为对于像我这样的人来说,有一个更完整的、也适用于std::vector<>::begin等const重载方法的更新答案会很有用。
基于我后续问题中的answer和answer,这里有一个更完整的答案。请注意,这只适用于C++11和更高版本。
#include <iostream>
#include <vector>
class EmptyClass{};
template <typename T>
class has_begin
{
private:
has_begin() = delete;
struct one { char x[1]; };
struct two { char x[2]; };
template <typename C> static one test( decltype(void(std::declval<C &>().begin())) * ) ;
template <typename C> static two test(...);
public:
static constexpr bool value = sizeof(test<T>(0)) == sizeof(one);
};
int main(int argc, char *argv[])
{
std::cout << std::boolalpha;
std::cout << "vector<int>::begin() exists: " << has_begin<std::vector<int>>::value << std::endl;
std::cout << "EmptyClass::begin() exists: " << has_begin<EmptyClass>::value << std::endl;
return 0;
}或者更短的版本:
#include <iostream>
#include <vector>
class EmptyClass{};
template <typename T, typename = void>
struct has_begin : std::false_type {};
template <typename T>
struct has_begin<T, decltype(void(std::declval<T &>().begin()))> : std::true_type {};
int main(int argc, char *argv[])
{
std::cout << std::boolalpha;
std::cout << "vector<int>::begin() exists: " << has_begin<std::vector<int>>::value << std::endl;
std::cout << "EmptyClass exists: " << has_begin<EmptyClass>::value << std::endl;
}注意,这里必须提供一个完整的示例调用。这意味着,如果我们测试resize方法的存在,那么我们将把resize(0)。
深度魔法解释
这个问题的第一个答案使用了test( decltype(&C::helloworld) );然而,当它测试的方法由于常量重载而不明确时,这是有问题的,从而使替换尝试失败。
为了解决这种多义性,我们使用了一个空语句,它可以接受任何参数,因为它总是被转换成一个noop,因此多义性是无效的,只要方法存在,调用就是有效的:
has_begin<T, decltype(void(std::declval<T &>().begin()))>下面是按顺序发生的事情:我们使用std::declval<T &>()创建一个可调用的值,然后可以调用begin。在此之后,begin的值将作为参数传递给空语句。然后,我们使用内置的decltype检索该空表达式的类型,以便可以将其用作模板类型参数。如果begin不存在,则替换是无效的,并根据SFINAE使用另一个声明。
https://stackoverflow.com/questions/257288
复制相似问题