【问题标题】:why compiler said: 'enable_if' cannot be used to disable this declaration为什么编译器说:'enable_if' 不能用于禁用此声明
【发布时间】:2015-09-10 13:47:01
【问题描述】:
template <bool Cond, typename Type = void>
using Enable_if = typename std::enable_if<Cond, Type>::type;

class Degree;

template <typename T>
constexpr inline bool Is_Degree() {
    return std::is_base_of<Degree, T>::value;
}

class Degree {
public:
    std::size_t inDeg = 0;
};

template <typename Satellite = Degree>
class Vertex: public Satellite {
public:
    explicit Vertex(int num): n(num) {}
private:
    std::size_t n;
};

template <typename Satellite = Degree>
class Edge {
public:
    // i want have different constructor depending on 
    // whether Vertex is (directly or indirectly) derived from Degree
    Edge(Enable_if<Is_Degree<Satellite>(), Vertex<Satellite> &>fromVertex,
        Vertex<Satellite> &toVertex)
        : from(fromVertex), to(toVertex){ ++to.inDeg; }
    Edge(Enable_if<!Is_Degree<Satellite>(), Vertex<Satellite> &>fromVertex, 
        Vertex<Satellite> &toVertex)
        : from(fromVertex), to(toVertex){}
private:
    Vertex<Satellite> &from;
    Vertex<Satellite> &to;
};

编译器在第 2 行抱怨:

'std::__1::enable_if&lt;false, Vertex&lt;Degree&gt; &amp;&gt;'中没有名为'type'的类型:'enable_if'不能用于禁用此声明。

如果我删除 Edge 的第二个构造函数没有错误。我想知道为什么,以及如何达到评论中描述的目的。

【问题讨论】:

  • 请注意,从 C++14 开始,您可以使用 std::enable_if_t 替换您的 Enable_if

标签: c++ c++11 templates sfinae enable-if


【解决方案1】:

这是因为替换发生在immediate context 之外(并且失败)。 std::enable_if 中涉及的类型模板参数应该直接来自一个模板,当上下文需要一个函数/特化时,编译器尝试实例化该模板,并且在此之前是未知的。否则,编译器可以随意拒绝您的代码。

一种可能的解决方法是将构造函数转换为模板,并将其参数默认为封闭类的模板参数的值:

template <typename S = Satellite>
//                 ^-----v
Edge(Enable_if<Is_Degree<S>(), Vertex<Satellite> &>fromVertex,
    Vertex<Satellite> &toVertex)
    : from(fromVertex), to(toVertex){ ++to.inDeg; }

template <typename S = Satellite>
//                 ^------v
Edge(Enable_if<!Is_Degree<S>(), Vertex<Satellite> &>fromVertex, 
    Vertex<Satellite> &toVertex)
    : from(fromVertex), to(toVertex){}

DEMO

【讨论】:

    猜你喜欢
    • 2018-11-15
    • 1970-01-01
    • 2021-02-18
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 2022-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多