Reputation: 18178
I'm trying to achieve something like this:
template<typename Bar>
class foo
{
public:
template<class = std::enable_if_t<std::is_constructible<Bar, int>::value>>
foo(int x)
: m_bar(x)
{ }
private:
Bar m_bar;
};
This yields the behavior
foo<int> a; // no error
foo<int> b(0); // no error
foo<std::string> c; // no error
foo<std::string> d(0); // error: none of the 3 overloads could convert all the argument types
as expected. Is there any disadvantage of this solution? What I don't like is that in either case foo::foo(int)
exists. I know that I could use the enable_if
in the template parameter list of foo
itself and specialize foo
for the two cases, but I don't want to duplicate the common code.
So, is this the best (or at least a sensible) option?
Upvotes: 0
Views: 806
Reputation: 48447
Is there any disadvantage of this solution?
Currently, the substitution takes place outside of an immediate context, so your approach will cause a hard compilation error as soon as you attempt to instantiate foo
with a type that is not constructible with an int
.
To introduce an immediate context, you'd need a dummy parameter:
template <typename T = Bar
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~v
, typename = std::enable_if_t<std::is_constructible<T, int>::value>>
foo(int x)
: m_bar(x)
{ }
Upvotes: 3