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;
};
The compiler complains at line 2:
"No type named '
type
' in 'std::__1::enable_if<false, Vertex<Degree> &>
': 'enable_if
' cannot be used to disable this declaration."
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.
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){}
DEMO
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With