首页 > 解决方案 > 使用 std::enable_if 的正确方法

问题描述

这些类之间有什么区别?正是这些方法与 enable_if。

/// Alias of std::enable_if...
template <bool B, typename T = void>
using Enable_if = typename std::enable_if<B, T>::type;

Template<typename T, std::size_t N>
class A {
   ...
    template <std::size_t NN = N,
          typename = Enable_if<NN == 2>>
    Some_Return_Type
    method(param1, param2)
    {}

    template <std::size_t NN = N,
              typename = Enable_if<NN == 1>>
    Some_Return_Type
    method(param1)
    {}


};


Template<typename T, std::size_t N>
class B {
   ...
    Enable_if<N == 2, Some_Return_Type>
    method(param1, param2)
    {}

    Enable_if<N == 1, Some_Return_Type>
    method(param1)
    {}
};

在我有的情况下,使用 enable_if 的正确方法是什么:

我想得到类似的东西:

Obj<int, 2> obj2;
Obj<int, 0> obj0;
Obj<int, 1> obj1;

如果我在 IDE 中编写,obj0.它只显示N == 0; obj1.只是N == 1,……

谢谢。

标签: c++c++11

解决方案


请注意,enable_if旨在触发 SFINAE:如果模板参数替换在其直接上下文中失败,则不是编译错误。

这正是发生的情况class A:当用户调用时a.method(...),编译器尝试实例化成员函数模板methodNN用常量替换参数,这可能会失败。

但是,如果B::method在类模板B实例化期间发生“错误”替换,则当编译器替换N. 失败发生在远离参数的直接上下文的地方,在这种情况下是template<typename T, std::size_t N> class B

这就是为什么在第二种情况下你会得到一个编译错误,而不是 SFINAE。

因此,要根据类模板参数启用/禁用成员函数,请使用第一种方法,根据需要组合条件。例如:

template <typename T, std::size_t N>
class A {
    template <std::size_t NN = N, typename = std::enable_if_t<NN == 2 || NN == 0>>
    void method(int, int)
    {}

    template <std::size_t NN = N, typename = std::enable_if_t<NN == 1 || NN == 0>>
    void method(int)
    {}
};

更新: enable_if 如何工作。大致可以这样实现:

template<bool, class T = void>
struct enable_if {};

template<class T>
struct enable_if<true, T> {
    using type = T;
};

请注意,如果第一个参数是false,enable_if没有 inner type,那么格式错误enable_if<false, int>::type。这就是触发 SFINAE 的原因。


推荐阅读