Using SFINAE to detect a member function [duplicate]

混江龙づ霸主 提交于 2019-12-04 03:29:21

Actually, your detection is potentially erroneous.

The problem is that all you are detecting is that C has a member size:

  • it could be an attribute
  • it could be a method with whatever signature
  • there could even be several methods (with various signatures)

If you wish to harden the detection, you should attempt to detect only the right size (for whatever right is). 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);
};

Edit: with overloads.

The trick to deal with incorrect size members is the really_has structure. I make no pretense that it is perfect, though...

In C++11, things are simpler (though no less verbose) because you can detect things by use directly. The equivalent trait is thus:

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

However, the recommended method in C++ is not to use traits if you can; in functions for example you can use decltype right in the type signature.

Yes:

char (*)[sizeof(&C::size)]
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!