关于c ++:使用SFINAE检测成员函数

Using SFINAE to detect a member function

本问题已经有最佳答案,请猛点这里访问。

在C++ 11中,为了找出一个类是否具有成员函数EDCOX1(0),可以定义以下测试助手:

1
2
3
4
5
6
7
8
9
10
11
template <typename T>
struct has_size_fn
{
    typedef char (& yes)[1];
    typedef char (& no)[2];

    template <typename C> static yes check(decltype(&C::size));
    template <typename> static no check(...);

    static bool const value = sizeof(check<T>(0)) == sizeof(yes);
};

在C++ 98中是否有类似的技巧,而不依赖于编译器扩展,如EDCOX1?1?


实际上,您的检测可能是错误的。

问题是,您所检测到的只是C有一个成员size

  • 它可能是一个属性
  • 它可以是一个带有任何签名的方法
  • 甚至可能有几种方法(有各种签名)

如果你想加强检测,你应该试着只检测右边的size(对于任何权利)。这是一个非常强硬的检测。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <typename T>
class has_size {
private:
  typedef char Yes;
  typedef Yes No[2];

  template <typename U, U> struct really_has;

  template <typename C> static Yes& Test(really_has <size_t (C::*)() const,
                                        &C::size>*);

  // EDIT: and you can detect one of several overloads... by overloading :)
  template <typename C> static Yes& Test(really_has <size_t (C::*)(),
                                        &C::size>*);

  template <typename> static No& Test(...);

public:
    static bool const value = sizeof(Test<T>(0)) == sizeof(Yes);
};

编辑:带有重载。

对付不正确的size成员的诀窍是really_has结构。但我并没有假装它是完美的,尽管…

在C++ 11中,事情更简单(虽然不那么冗长),因为你可以通过直接使用来检测事物。因此,等效特性是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <typename T>
class has_size {
private:
  typedef char Yes;
  typedef Yes No[2];

  template<typename C> static auto Test(void*)
    -> decltype(size_t{std::declval<C const>().size()}, Yes{});

  template<typename> static No& Test(...);

public:
    static bool const value = sizeof(Test<T>(0)) == sizeof(Yes);
};

但是,C++中推荐的方法是不使用特性;如果在函数中,您可以在类型签名中使用EDCOX1(5)右。


对:

1
char (*)[sizeof(&C::size)]