【问题标题】:Check if class has function with signature检查类是否具有签名功能
【发布时间】:2014-07-27 19:59:16
【问题描述】:

此站点上还有其他使用 SFINAE 但使用非 C++11 代码的答案,还有其他使用 C++11 代码(如 decltypes)来简化此过程的答案。但是,我不确定如何检查一个类是否具有具有特定签名的函数。

我想检查一个类是否具有receive(const Event &) 函数,其中Event 是调用检查函数时指定的类类型。

【问题讨论】:

  • There are other answers on this site using SFINAE but with non C++11 code:不是真的,看看this
  • 我认为这不能正确回答我的问题,但如果您尝试像这样创建指向函数的函数指针,编译器似乎会抱怨:void(Reciever::*func)(const Event &) = &Reciever::recieve;
  • @user975989:你的问题真的不清楚。你的例子works for me。由 40two 链接的 answer 到底有什么问题?
  • 没什么好说的,我只是想知道是否有一种不那么冗长的方式来使用 decltypes 等。之前没用过是因为不知道,是我的错。

标签: c++ c++11 sfinae


【解决方案1】:

我所知道的最好的方法是检查您是否可以真正调用该函数,以及它是否返回您期望的类型。这是一个如何检测类C 是否具有receive 方法的示例,该方法将const Event& 作为参数并“返回”void。检测关心该方法是直接在类C 中实现还是在C 派生的某个基类中实现,也不关心是否有进一步的默认参数。根据需要进行调整。

template< typename C, typename Event, typename = void >
struct has_receive
  : std::false_type
{};

template< typename C, typename Event >
struct has_receive< C, Event, typename std::enable_if<
    std::is_same<
        decltype( std::declval<C>().receive( std::declval<const Event&>() ) ),
        void
    >::value
>::type >
  : std::true_type
{};

【讨论】:

  • 我无法让它在 VS2013 Nov CTP 中编译。
  • @user975989 这是符合标准的代码,可与(至少)GCC 和 Clang 一起使用。我没有使用 Windows/VS,所以我无法帮助找到解决方法,抱歉。
【解决方案2】:

您可以使用以下内容来匹配确切的签名:

template <typename U, typename Event>
class has_receive
{
private:
    template<typename T, T> struct helper;
    template<typename T>
    static std::uint8_t check(helper<void (T::*)(const Event &), &T::receive>*);
    template<typename T> static std::uint16_t check(...);
public:
    static
    constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t);
};

【讨论】:

  • 我想知道这实际上有多大用处,因为它会拒绝像 void(T::*)(const Event&amp;) const 这样的成员,例如。我不知道为什么 OP 需要这个,但在我看来,没有理由寻找确切的签名。
【解决方案3】:

有关于宏的帮助:

#define DEFINE_METHOD_CHECKER(RETURN_TYPE, METHOD_NAME, PARAMETERS)     \
template<typename T>                                                    \
struct Is ## METHOD_NAME ## MemberFunctionExists                        \
{                                                                       \
private:                                                                \
    typedef char True;                                                  \
    typedef char (&False)[2];                                           \
    template<typename U, RETURN_TYPE (U::*)PARAMETERS = &U::METHOD_NAME>\
    struct Checker                                                      \
    {                                                                   \
        typedef True Type;                                              \
    };                                                                  \
    template<typename U>                                                \
    static typename Checker<U>::Type Tester(const U*);                  \
    static False Tester(...);                                           \
public:                                                                 \
    enum { value = (sizeof(Tester(static_cast<const T*>(0))) == sizeof(True)) }; \
}

// IsMethodMemberFunctionExists<T>::value
DEFINE_METHOD_CHECKER(int, Method, (bool));
// IsTestMemberFunctionExists<T>::value
DEFINE_METHOD_CHECKER(int*, Test, (int&, char));

#include <iostream>

class Exists
{
public:
    int Method(bool);
    int* Test(int&, char);

};

class NotExists
{
};

int main()
{
    std::cout << IsMethodMemberFunctionExists<Exists>::value << std::endl;
    std::cout << IsTestMemberFunctionExists<Exists>::value << std::endl;

    std::cout << IsMethodMemberFunctionExists<NotExists>::value << std::endl;
    std::cout << IsTestMemberFunctionExists<NotExists>::value << std::endl;
}

因此,在您的情况下,您需要定义一些检查器 - 一种检查器用于一种类型的事件:

// void recieve(const Event1&)
DEFINE_METHOD_CHECKER(void, recieve, (const Event1&));

// void recieve(const Event2&)
DEFINE_METHOD_CHECKER(void, recieve, (const Event2&));

【讨论】:

    猜你喜欢
    • 2021-10-31
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多