Problem
Suppose we have a (fictional) class template C<T>
with a conditionally explicit default constructor. The default constructor should be explicit if and only if std::is_same_v<T, int>
.
A search on "[c++] conditionally explicit" returns this result: Constructor conditionally marked explicit.
A failed solution
The accepted answer gives an example:
struct S { template <typename T, typename std::enable_if<std::is_integral<T>::value, bool>::type = false > S(T) {} template <typename T, typename std::enable_if<!std::is_integral<T>::value, bool>::type = false> explicit S(T) {} };
Modifying the example slightly gives this implementation which uses the familiar approach of std::enable_if
:
template <class T>
class C {
public:
template <std::enable_if_t<std::is_same_v<T, int>, int> = 0>
C() {}
template <std::enable_if_t<!std::is_same_v<T, int>, int> = 0>
explicit C() {}
};
Unfortunately, this does not even compile: demo
prog.cc: In instantiation of 'class C<int>':
prog.cc:15:10: required from here
prog.cc:10:12: error: no type named 'type' in 'struct std::enable_if<false, int>'
10 | explicit C() {}
| ^
prog.cc: In instantiation of 'class C<double>':
prog.cc:18:13: required from here
prog.cc:7:3: error: no type named 'type' in 'struct std::enable_if<false, int>'
7 | C() {}
| ^
The problem seems to be caused by the omission of a template parameter of the constructor, disabling SFINAE.
Question
- Why does this not compile?
- What is a possible implementation?
I would like to avoid specializing the class if possible.