代码之家  ›  专栏  ›  技术社区  ›  PatrykB

为什么`SFINAE`(std::enable\u if)使用bool文本而不是`true\u t`/`false\u t`标记类?

  •  1
  • PatrykB  · 技术社区  · 7 年前

    我正在努力学习 SFINAE tutorial

    让我们假设我遇到这样的情况(包括重新实现 std::enable_if enable_if )

    // A default class (class type) declaration. Nothing unusual.
    template <bool, typename T = void>
    struct enable_if
    {}; 
    
    // A specialisation for <true, T> case. I understand 'why-s' of this. 
    // -- 'why-s': if I attempt to access 'enable_if<false, T>::type' (which does not exist) I will get a substitution failure and compiler will just "move-on" trying to match "other cases".
    template <typename T>
    struct enable_if<true, T> {
        typedef T type;
    };
    
    // Here lies my problem:
    template <class T,
             typename std::enable_if<std::is_integral<T>::value,T>::type* = nullptr>
    void do_stuff(T& t) { /* do stuff */ };
    


    (1) bool 文字的( true / false 启用\u如果 / 我将创建一个标记类 true_t (或 True false_t (或 False )详情如下:

    class true_t {}; // or True
    
    class false_t {}; // or False
    
    template<typename T>
    class is_integral // just to have "something" to use with "enable_if"
    {
        using result = false_t;
    };
    
    template<>
    class is_integral<int32_t> // same with all other int types
    {
        using result = true_t;
    };
    
    template <typename B, typename T = void>
    struct enable_if
    {}; 
    
    template <typename T>
    struct enable_if<true_t, T>
    {
        using type = T;
    };
    


    typename T 模板参数。直接实施不是更容易/更好吗 启用\u如果

    template <typename B>
    struct enable_if
    {}; 
    
    template <>
    struct enable_if<true_t>
    {
        using type = void; // the 'type' exists therefore substitution failure will not occur. 
    };
    


    我很清楚,我所有的建议都远远低于目前的解决方案 我刮胡子了吗?(甚至没有意识到……)


    std::enable_if</* ... */>::type* = nullptr
    

    完成?这是我现在无法理解的。。。

    2 回复  |  直到 7 年前
        1
  •  4
  •   NathanOliver    7 年前

    bool 文字的( true false )。我知道它们是正确的,模板可以接受原始数据类型(普通的旧数据类型)的编译时常量值,但如果我负责设计 enable_if / 假的 我将创建一个标记类 true_t (或 True )及 false_t False )如下

    使用标记类型而不仅仅是bool的问题是,您必须为代码增加额外的复杂性。如果要检查编译时条件,如 sizeof 比如说,你不能就这么做 sizeof(T) == 8 . 您必须进行一个抽象来进行检查并返回适当的标记类型。

    我觉得多余的第二件事是需要具体说明 typename T 启用\u如果

    typename

    template< bool B, class T = void >
    using enable_if_t = typename enable_if<B,T>::type;
    template< class T >
    inline constexpr bool is_integral_v = is_integral<T>::value;
    

    这允许您重写

    template <class T,
             typename std::enable_if<std::is_integral<T>::value,T>::type* = nullptr>
    void do_stuff(T& t) { /* do stuff */ };
    

    template <class T,
             std::enable_if_t<std::is_integral_v<T>,T>* = nullptr>
    void do_stuff(T& t) { /* do stuff */ };
    

    虽然我更喜欢用bool来表示 enable_if_t 喜欢

    template <class T,
             std::enable_if_t<std::is_integral_v<T>, bool> = true>
    void do_stuff(T& t) { /* do stuff */ };
    

    std::enable_if</* ... */>::type* = nullptr
    

    完成?

    它生成一个指向 std::enable_if

    typename = typename std::enable_if</* ... */>::type
    

    因此,不是使用非类型参数,而是使用类型参数。它们都完成了相同的任务,但后者不能为不同的对象重载函数 启用\u如果 启用\u如果 是的。

        2
  •  3
  •   super    7 年前

    true false ,即 std::true_type std::false_type .

    enable_if 使用此参数而不是布尔参数。你再也不能做像这样的事情了 std::enable_if<1 == 1>::type 自从 1 == 1 计算结果为bool。你想在这里测试的大部分东西也是如此。

    启用\u如果 因为它们包含一个 value 祝你生日快乐 operator() 该返回值表示该值。

    对于第2点,能够指定所需的类型只是一种方便 启用\u如果 void ,但如果你愿意,你可以很容易地推导出 int double 发射型计算机断层扫描仪。这有时很有用。