Reputation: 333
How can I remove the ambiguity of this code ? (Try it here)
template <typename T>
inline void f()
{
}
template<typename T, typename ... Args>
inline void f()
{
f<Args...>();
}
int main()
{
f<char, double, int>();
return 0;
}
Here is the solution i found ... but I'm not really satisfied with it. (Try it here)
template <int N>
inline void f()
{
}
template<int N, typename T, typename ... Args>
inline void f()
{
f<42,Args...>();
}
int main()
{
f<42,char, double, int>();
return 0;
}
Is it possible to give a template specialization for an empty parameter pack ?
Upvotes: 1
Views: 527
Reputation: 29193
You haven't specialized f
at all! You've overloaded it. That is, you have two templates under the name f
, and it is ambiguous which one you want to use. Consider the call f<int>()
. Do you mean to instantiate the first template with T = int
, or the second with T = int; Args = {}
? If you want to properly specialize f
, I think it actually needs to be wrapped into a class (to allow partial specialization):
template<typename T, typename... Args>
struct f_wrapper
{
static inline void f()
{
f_wrapper<Args...>::f();
}
};
Then you can use this syntax to specialize it:
template<typename T>
// the brackets v v distinguish specialization from overloading
// you can't overload classes anyway, but it's important for functions
struct f_wrapper<T>
{
static inline void f()
{
}
};
Now, there is one class template named f
, which has two specializations. There is no ambiguity in f_wrapper<int>::f()
. The one and only template is instantiated with T = int; Args = {}
, and then this is used to choose the Args = {}
specialization (the second definition).
You can then proceed to wrap this:
template<typename T, typename... Args>
inline void f() { f_wrapper<T, Args...>::f(); }
Upvotes: 1
Reputation: 181027
What you can do is add an another template parameter to the variadic overload like
template<typename T, typename U, typename ... Args>
inline void f()
{
f<U, Args...>();
}
This meas the function can only be called with 2 or more parameters so there is no more ambiguity between a single parameter or a single parameter and empty pack.
Depending on what you want to achieve in the function you might also be able to switch to using a fold expression if you can use C++17
Upvotes: 4