Using SFINAE to detect a member function [duplicate]

ⅰ亾dé卋堺 提交于 2019-12-21 09:15:48

问题


In C++11, to find out whether a class has a member function size, you could define the following test helper:

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

Is there a similar trick for doing this in C++98 without relying on compiler extensions such as typeof?


回答1:


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.




回答2:


Yes:

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


来源:https://stackoverflow.com/questions/18570285/using-sfinae-to-detect-a-member-function

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