为什么编译器说:'enable_if' 不能用于禁用此声明
why compiler said: 'enable_if' cannot be used to disable this declaration
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 行报错:
"No type named 'type
' in 'std::__1::enable_if<false, Vertex<Degree> &>
': 'enable_if
' cannot be used to disable this declaration."
去掉Edge的第二个构造函数就没有错误了。我想知道为什么,以及如何实现我在评论中描述的目的。
这是因为替换发生在(并且失败)immediate context 之外。 std::enable_if
中涉及的类型模板参数应该 直接 来自编译器在上下文要求存在 function/specialization 时尝试实例化的模板,并且是在那之前未知。否则,编译器可以随意拒绝您的代码。
一种可能的解决方法是将构造函数转换为模板,并将它们的参数默认为封闭 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){}
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 行报错:
"No type named '
type
' in 'std::__1::enable_if<false, Vertex<Degree> &>
': 'enable_if
' cannot be used to disable this declaration."
去掉Edge的第二个构造函数就没有错误了。我想知道为什么,以及如何实现我在评论中描述的目的。
这是因为替换发生在(并且失败)immediate context 之外。 std::enable_if
中涉及的类型模板参数应该 直接 来自编译器在上下文要求存在 function/specialization 时尝试实例化的模板,并且是在那之前未知。否则,编译器可以随意拒绝您的代码。
一种可能的解决方法是将构造函数转换为模板,并将它们的参数默认为封闭 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){}