模板化检查是否存在类成员函数?

新手上路,请多包涵

是否可以编写一个模板来根据类上是否定义了某个成员函数来改变行为?

这是我想写的一个简单的例子:

 template<class T>
std::string optionalToString(T* obj)
{
    if (FUNCTION_EXISTS(T->toString))
        return obj->toString();
    else
        return "toString not defined";
}

因此,如果 class T toString() 定义了 --- ,那么它会使用它;否则,它不会。我不知道该怎么做的神奇部分是“FUNCTION_EXISTS”部分。

原文由 andy 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 708
2 个回答

是的,使用 SFINAE,您可以检查给定的类是否提供了某种方法。这是工作代码:

 #include <iostream>

struct Hello
{
    int helloworld() { return 0; }
};

struct Generic {};

// SFINAE test
template <typename T>
class has_helloworld
{
    typedef char one;
    struct two { char x[2]; };

    template <typename C> static one test( decltype(&C::helloworld) ) ;
    template <typename C> static two test(...);

public:
    enum { value = sizeof(test<T>(0)) == sizeof(char) };
};

int main(int argc, char *argv[])
{
    std::cout << has_helloworld<Hello>::value << std::endl;
    std::cout << has_helloworld<Generic>::value << std::endl;
    return 0;
}

我刚刚使用 Linux 和 gcc 4.14.3 对其进行了测试。我不知道它是否可以移植到运行不同编译器的其他平台。

原文由 Nicola Bonelli 发布,翻译遵循 CC BY-SA 4.0 许可协议

c++20 之前,简单情况下的简单选项:

如果您知道您的类是默认可构造的,我们可以使语法更简单。

我们将从最简单的情况开始:默认可构造并且我们知道预期的返回类型。示例方法:

 int foo ();

我们可以在没有 declval 的情况下编写类型特征:

 template <auto v>
struct tag_v
{
    constexpr static auto value = v;
};

template <class, class = int>
struct has_foo_method : tag_v<false> {};

template <class T>
struct has_foo_method <T, decltype(T().foo())>
    : tag_v<true> {};

演示

请注意,我们将默认类型设置为 int 因为这是 foo 的返回类型。

如果有多个可接受的返回类型,那么我们将第二个参数添加到 decltype 这与默认类型相同,覆盖第一个参数:

 decltype(T().foo(), int())

演示

(这里的 int 类型并不重要 - 我使用它是因为它只有 3 个字母)

原文由 Elliott 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题