Given
template<class... Args>
struct foo {
function<void(Args...)> m_function;
unique_ptr<tuple<Args...>> m_args;
foo(const std::function<void(Args...)>& func, Args... args) :
m_function{ func }, m_args{ new tuple<Args...>(args...) } {
cout << "ctor 1" << endl;
}
// <some template wizardry here>
foo(const std::function<void(Args...)>& func) :
m_function{ func } {
cout << "ctor 2" << endl;
}
};
I would like ctor2 to be instantiated only when sizeof...(Args) != 0
(or else I get a collision..).
This right here seems to work (no collisions)
template<Args...>
foo(const std::function<void(Args...)>& func) :
m_function{ func } {
cout << "ctor 2" << endl;
}
but I have no idea how/why or if it's reliable.
Also Id probably use something like
std::enable_if<sizeof...(Args) != 0, ???>
How can I resolve this using std::enable_if
and what is going on in my 2nd code sample ?
As pointed by Johannes Schaub - litb in a comment, you can simply add a variadic list of unused template parameters, just to transform your second contructor in a template one and give precedence (avoiding the collision) to the first one that isn't a template constructor.
So you can simply write
template <typename ...>
foo (std::function<void(Args...)> const & func)
: m_function{ func }
{ std::cout << "ctor 2" << std::endl; }
But to satisfy your request
I would like ctor2 to be instantiated only when
sizeof...(Args) != 0
you can try with (less elegant but, maybe, more comprehensible)
template <bool B = (sizeof...(Args) > 0u),
std::enable_if_t<B, bool> = true>
foo (std::function<void(Args...)> const & func)
: m_function{ func }
{ std::cout << "ctor 2" << std::endl; }