How to solve this variadic template ambiguity

Advertisements

The following code compiles and runs fine as long as someFuncTemplate(func1) is commented out. However, once it is uncommented, compilation fails with the error " ‘value’ is not a member of ‘Arity<int (*)(int, int)>’ " compile error, which I believe is due to the compiler selecting the first template instead of the second one at Arity<F>::value. I tried removing the brackets from the first template, but the issue remains, just this time with an "incomplete type" compilation error.

How can I force the compiler to select the correct template when I use Arity<F>?

#include <iostream>

template <typename T>
struct Arity {};

template <typename Ret, typename... Args>
struct Arity<Ret(Args...)>
    : std::integral_constant<size_t, sizeof...(Args)> 
{};

int func1(int a, int b) { return a + b; }

template <typename F>
void someFuncTemplate(F)
{
    std::cout << Arity<F>::value;
}

int main()
{
    std::cout << Arity<decltype(func1)>::value << '\n';
    //someFuncTemplate(func1);
}

>Solution :

You need to add another specialization for the second case:

template <typename Ret, typename... Args>
struct Arity<Ret (*)(Args...)> : Arity<Ret(Args...)> {};
//               ^^^

You could also add

template <typename Ret, typename... Args>
struct Arity<Ret (&)(Args...)> : Arity<Ret(Args...)> {};

in order to make a function declaration such as the below working:

template <typename F>
void someFuncTemplate(F&&) {
    std::cout << Arity<F>::value;
}

Demo

Leave a ReplyCancel reply