1

对于最近发布的一些问题,我一直在研究一些解决方案,其中原始提问者一直试图查询给定类中是否存在方法。我一直在尝试使用 SFINAE 方法开发解决方案,但不幸的是我一直空着。

这是我尝试的一种解决方案,该解决方案不适用于允许我们检测另一个类是否具有名为的方法的类function()

#include <iostream>

using namespace std;

struct sample_class
{
    void function() {}
};


template<typename T>
class test_size_call
{
    private:
        typedef char yes;
        typedef char (&no)[2];
        int tester[1];

        template <unsigned int>
        struct helper { static const unsigned int value = 1; };

        template<typename R>
        static yes test(int (&a)[helper<sizeof(std::declval<R>().function(), 0)>::value]);

        /* template<typename R>
        static no test(...); */

    public:
        static const bool value = (sizeof(test<T>(tester)) == sizeof(yes));
};


int main()
{
    cout << "Has function() method: " << test_size_call<sample_class>::value << endl;
        return 0;
}

结果,如果您取消注释全部test功能,则继续显示为false. 注释掉该函数后,我得到一个编译器错误,即没有版本test可以接受int (&)[1]参数。我很好奇为什么declval<R>().function()似乎没有正确实例化。例如,如果我将其更改为非常明确的内容,declval<T>().function()那么它就可以工作。不幸的是,这不是 SFINAE,因为如果该类没有function()方法,而不是静默失败,我会收到编译器错误。

我敢肯定,我在这里缺少一些非常简单的东西。感谢您的任何帮助,您可以提供。

4

2 回答 2

3

一定是您的编译器有问题,Clang 正确打印1并且0对于以下代码:

#include <utility>

template<typename T>
class test_size_call
{
    private:
        typedef char yes;
        typedef char (&no)[2];
        int tester[1];

        template <unsigned int>
        struct helper { static const unsigned int value = 1; };

        template<typename R>
        static yes test(int (&a)[helper<sizeof(std::declval<R>().function(), 0)>::value]);

        template<typename R>
        static no test(...);

    public:
        static const bool value = (sizeof(test<T>(tester)) == sizeof(yes));
};

#include <iostream>

struct sample_class
{
    void function() {}
};

struct sample_class2{};

int main()
{
    std::cout << "Has function() method: " << test_size_call<sample_class>::value << '\n';
    std::cout << "Has function() method 2: " << test_size_call<sample_class2>::value << '\n';
    return 0;
}

虽然 GCC 4.5.1没有. 请注意,正如此处指出的,它在 GCC 4.7 中已修复。

于 2012-01-18T16:21:32.140 回答
2

Jason,如果您使用的是 Visual C++,那么 SFINAE 在那里不能很好地工作(特别是它似乎不适用于用户定义类型的数据成员,但它可能仍然适用于函数)。

对于其他编译器,您可以使用以下内容:

template <typename T>
struct has_function
{
  template <typename U, void (U::*f) ()> struct match_;
  template<typename > static char (&select_(...))[2];
  template<typename U> static char (&select_(match_<U, &U::function>* ))[1];

  enum { value = sizeof(select_<T>(0)) == 1 };
};

struct get
{
  void function();
};

int main()
{
  int t[(int)has_function<get>::value];
  (void)t;
}

Visual C++ 错误有一个解决方法,请在此处查看“解决方法”选项卡: http ://connect.microsoft.com/VisualStudio/feedback/details/718729/c-type-equality-not-recognized-under-sfinae-context

于 2012-01-18T16:24:30.040 回答