Reputation: 1156
Please tell me why this answer works.
Origin version:
template <typename Policy,
typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type >
struct Foo;
template <typename Policy>
struct Foo {
Foo();
};
template <typename Policy>
Foo<Policy>::Foo() {
}
Edited version:
template <typename Policy,
typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type >
struct Foo;
template <typename Policy>
struct Foo<Policy> { // <Policy> added!
Foo();
};
template <typename Policy>
Foo<Policy>::Foo() {
}
Upvotes: 2
Views: 756
Reputation: 93274
This happened:
The author posted working code (<Policy>
was present);
There was some discussion in the comments that led the author to edit the code, and he made a mistake (<Policy>
was removed);
I rectified the mistake putting back the missing <Policy>
.
Can anybody explains why even the edited version works?
When you attempt to instantiate Foo<T>
, the declaration with the default template parameters is taken into account by the compiler. The default parameter is evaluated and if std::is_base_of<BasePolicy, Policy>::value
is false
then enable_if
produces a SFINAE-friendly error.
If std::is_base_of<BasePolicy, Policy>::value
is true
, the partial specialization is chosen.
template <typename Policy>
struct Foo<Policy> {
Foo() { }
};
// is equivalent to
template <typename Policy>
struct Foo<Policy, void> {
Foo() { }
};
The above specializations are equivalent because typename std::enable_if<true>::type
is void
by default.
Upvotes: 3