【问题标题】:SFINAE C++ method checkSFINAE C++ 方法检查
【发布时间】:2016-10-30 13:35:29
【问题描述】:

我正试图绕开 SFINAE。 我们用它来检查一个类是否有一个名为“Passengers”的方法。

通过一些在线示例,我们构建了以下模板类。

#ifndef TYPECHECK
#define TYPECHECK

#include "../Engine/carriage.h"

namespace TSS{

template<typename T>
class has_passengers{
private:
    typedef char one;
    typedef struct{char a[2];} two;

    template<typename C> static one test( decltype(&C::Passengers) );
    template<typename C> static two test(...);
public:
    static bool const value = sizeof(test<T>(0)) == sizeof(one);
};

template<typename T>
struct CarriageTypeCheck{
    static_assert(has_passengers<T>::value, "Train initialized with illegal carriage");
};

}


#endif // TYPECHECK

我知道如何选择两种测试方法中的任何一种,但我不明白为什么test&lt;T&gt; 在以下行中被初始化为 0:

    static bool const value = sizeof(test<T>(0)) == sizeof(one);

我看不出 0 对检查的工作有多重要。 另一件事 - 为什么使用 decltype ?

【问题讨论】:

  • 你没有检查类是否有成员函数Passengers。您正在检查它是否有成员 Passengers,这可能是一个函数,但不一定是。
  • 好点!谢谢!

标签: c++ templates metaprogramming sfinae decltype


【解决方案1】:

第一个重载函数(可能)将指向类方法的指针作为参数。由于 C++ 继承自 C,值 0 可转换为 NULL 指针,或 nullptr。所以,如果 SFINAE 没有踢出第一个重载函数,test&lt;T&gt;(0) 就成为一个有效的函数调用,它的sizeof 等于sizeof(one)。否则,这将解析为第二个重载函数调用。

关于为什么使用decltype 的简短回答:否则它将不是有效的 C++。在函数声明中,函数的参数必须是类型,指定函数参数的类型。 &amp;C::Passengers 不是类型(在其预期用途的上下文中),因此这不是有效的 C++。 decltype() 其中自动获取其参数的类型,使其成为有效的 C++。

【讨论】:

  • 好的。但是如果 T 没有乘客,它不等于“sizeof(two)”吗?那么调用将是 test(nullpointer) 并且大小将是 2?
  • @BenjaminLarsen 如果T没有Passengers,类型推导失败,函数模板将被忽略;这就是 SFINAE 的工作原理。在这种情况下没有这样的规则来传递空指针,没有 SFINAE,你会得到一个编译错误。
  • 我想我现在明白了!谢谢你们。
【解决方案2】:

我看不出 0 对检查的工作有多重要。

因为0 可以用作两种情况的参数(即两个重载的test);用于成员指针(视为空指针)和可变参数...

另外一件事——为什么要使用 decltype?

decltype用于描述成员指针的类型(即&amp;C::Passengers)作为test的参数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-15
    • 2020-05-11
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多