C++ 为什么编译器说';如果',则启用#u;无法用于禁用此声明 模板 使用Enable_if=typename std::Enable_if::type; 班级学位; 模板 constexpr内联布尔是_度(){ return std::是::value的_base_; } 等级{ 公众: 标准:尺寸指数=0; }; 模板 类别:公共卫星{ 公众: 显式顶点(int num):n(num){} 私人: 标准:尺寸; }; 模板 阶级边缘{ 公众: //我想有不同的构造函数取决于 //顶点是否(直接或间接)从度派生 边(启用_iffromVertex, 顶点(顶点和顶点) :from(fromVertex),to(toVertex){++to.inDeg;} 边(启用_if(),顶点&>fromVertex, 顶点(顶点和顶点) :from(fromVertex),to(toVertex){ 私人: 顶点&from; 顶点&to; };

C++ 为什么编译器说';如果',则启用#u;无法用于禁用此声明 模板 使用Enable_if=typename std::Enable_if::type; 班级学位; 模板 constexpr内联布尔是_度(){ return std::是::value的_base_; } 等级{ 公众: 标准:尺寸指数=0; }; 模板 类别:公共卫星{ 公众: 显式顶点(int num):n(num){} 私人: 标准:尺寸; }; 模板 阶级边缘{ 公众: //我想有不同的构造函数取决于 //顶点是否(直接或间接)从度派生 边(启用_iffromVertex, 顶点(顶点和顶点) :from(fromVertex),to(toVertex){++to.inDeg;} 边(启用_if(),顶点&>fromVertex, 顶点(顶点和顶点) :from(fromVertex),to(toVertex){ 私人: 顶点&from; 顶点&to; };,c++,c++11,templates,sfinae,enable-if,C++,C++11,Templates,Sfinae,Enable If,编译器在第2行抱怨: “在“标准::”中没有名为“类型”的类型:“启用”:“启用”不能用于禁用此声明。” 如果删除Edge的第二个构造函数,则不会出现错误。我想知道为什么,以及如何达到我在评论中所描述的目的。这是因为替代发生(并失败)在外部。如果中涉及的类型模板参数应该直接来自一个模板,当上下文要求函数/专门化存在时,编译器试图实例化该模板,并且在该点之前未知。否则,编译器可以自由地拒绝您的代码 一种可能的解决方法是将构造函数转换为模板,并将其参数默认为封闭类的模板参数值: template &

编译器在第2行抱怨:

在“
标准::”中没有名为“
类型
”的类型:“
启用
”:“
启用
”不能用于禁用此声明。


如果删除Edge的第二个构造函数,则不会出现错误。我想知道为什么,以及如何达到我在评论中所描述的目的。

这是因为替代发生(并失败)在外部。如果
中涉及的类型模板参数应该直接来自一个模板,当上下文要求函数/专门化存在时,编译器试图实例化该模板,并且在该点之前未知。否则,编译器可以自由地拒绝您的代码

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

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;
};
模板
//^---v
边(启用_iffromVertex,
顶点(顶点和顶点)
:from(fromVertex),to(toVertex){++to.inDeg;}
模板
//^---v
边(启用_if(),顶点&>fromVertex,
顶点(顶点和顶点)
:from(fromVertex),to(toVertex){

请注意,自C++14以来,您有
std::enable_if_t
来替换
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){}