Variadic Templates When Specifying a Method Receive Function

The following code looks like it should work fine, but it creates

C2738: could not deduce template argument for 'Type'.

in VS2013.

template <typename ReturnType, typename...Args>
uint GetParameterSize(ReturnType(*method)(Args...))
{
    return ParameterSize<Args...>();
}

template <typename Type, typename...Remaining>
uint ParameterSize()
{
    uint output = sizeof(Type);

    if (sizeof...(Remaining) > 0)
    {
        output += ParameterSize<Remaining...>();
    }

    return output;
}

void MyMethod3(int a, char b, int c )
{
}

// Elsewhere
uint size = GetParameterSize(&MyMethod3);

I thought, "Oh, maybe because he has no final state." So I added:

template <typename Type>
uint ParameterSize()
{
    return sizeof(Type);
}

What led to

C2668: 'ParameterSize' ambiguous call to overloaded function.

I mean, it looks quite simple, and I think it should work. How does the compiler not output arguments? I am new to variable templates, so something may be missing for me, but some of them will be appreciated. Thanks!

+4
source share
3 answers

The simplest fix I can think of is to call overload resolution:

template <typename Type>
constexpr unsigned ParameterSize(int)
{
    return sizeof(Type);
}

template <typename Type, typename...Remaining>
constexpr unsigned ParameterSize(...)
{
    return sizeof(Type) + ParameterSize<Remaining...>(42);
}

template <typename ReturnType, typename...Args>
constexpr unsigned GetParameterSize(ReturnType(*method)(Args...))
{
    return ParameterSize<Args...>(42);
}

void MyMethod3(int a, char b, int c )
{
}

int main()
{
    // Elsewhere
    unsigned size = GetParameterSize(&MyMethod3);
}

, int (, 42), (ParameterSize<one_argument>(42)).

+2
  if (sizeof...(Remaining) > 0)
    {
        output += ParameterSize<Remaining...>();
    }

, , . , Remaining 0, ParamaterSize<>(), .

.

template<typename ... Args>
struct ParameterSize;   
{
   static const uint value = 0;
};

template<typename Type, typename... Remain>
struct ParameterSize<Type, Remain...>
{
   static const uint value = sizeof(Type) + ParameterSize<Remain...>::value;
};

template <typename ReturnType, typename...Args>
uint GetParameterSize(ReturnType(*method)(Args...))
{
    return ParameterSize<Args...>::value;
}

http://ideone.com/6aYRzI

+3

, , . , , sizeof(Type), , , :

    #include <iostream>
    #include <algorithm>

    template <class ... Args>
    unsigned ParameterSize()
    {
        unsigned sizes[sizeof...(Args)] = {sizeof(Args)...};
        return std::accumulate(std::begin(sizes), std::end(sizes), 0);
    }

    template <typename ReturnType, typename...Args>
    uint GetParameterSize(ReturnType(*method)(Args...))
    {
        return ParameterSize<Args...>();
    }

    void MyMethod(int,int,int){}

    int main()
    {
        std::cout << GetParameterSize(&MyMethod) << std::endl;
    }

Since you already had the runtime code in your example, I assume that you are not opposed to having the work done at runtime.

+1
source

All Articles