使用SFINAE检测成员函数

时间:2013-09-02 09:52:51

标签: c++ sfinae c++98

在C ++ 11中,要确定某个类是否具有成员函数size,您可以定义以下测试助手:

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中执行此操作是否有类似的技巧而不依赖于typeof等编译器扩展?

2 个答案:

答案 0 :(得分:8)

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

问题在于您所检测到的只是C有成员size

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

如果您希望强化检测,则应尝试仅检测 size(无论是什么权利)。 Here is such a hardened detection

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);
};

修改: with overloads

处理不正确的size成员的技巧是really_has结构。我不假装它是完美的,但是......

在C ++ 11中,things are simpler(虽然同样详细)因为你可以直接通过使用来检测事物。因此,等效特征是:

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 ++中推荐的方法是不使用特征;例如,在函数中,您可以在类型签名中使用decltype

答案 1 :(得分:1)

是:

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