问题描述
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行抱怨:
如果删除Edge的第二个构造函数,则没有错误.我想知道原因,以及如何达到评论中所述的目的.
There is no error if I remove the second constructor of Edge. I want know why, and how to attain my purpose as described in the comment.
推荐答案
这是因为替换发生在即时上下文 . std :: enable_if
中涉及的类型模板参数应该直接来自模板,当上下文要求存在功能/专业化功能时,编译器会尝试实例化该模板,并且在此之前未知.否则,编译器可以自由拒绝您的代码.
This is because substitution takes place (and fails) outside of an immediate context. Type template parameters involved in std::enable_if
should come directly from a template that a compiler attempts to instantiate when a function/specialization is required to exist by a context, and that are unknown prior to that point. Otherwise, the compiler is free to reject your code.
可能的解决方法是将构造函数转换为模板,并将其参数默认为包含类的模板参数的值:
A possible workaround is to turn the constructors into templates and default their parameters to the value of the template parameter of the enclosing class:
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){}
这篇关于为什么编译器说:'enable_if'不能用于禁用此声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!