Search code examples
c++c++11templatesvariadic-templatesauto

Why is "no matching overload found" error appearing even though I have them defined


Going through some template tutorial I encountered the following error:

Error (active) E0304 no instance of overloaded function "sum" matches the argument list Templates

I know that I am dealing with variadic templates here but I cannot see why the overload for multiple parameters is not being detected. Also worth mentioning that the exact code in the tutorial I am following does not throw any error.

#include <iostream>
#include <string>
#include <memory>
#include <tuple>
#include <array>
#include <vector>
#include <complex>

using namespace std;



typedef complex<double> cd;




// specialization for when there is only one argument
template <typename T>
T sum(T t) { return t; }

// -> defines a return type as a result of sum values
template<typename T, typename ...U>
auto sum(T t, U ...u) -> decltype(t + sum(u...))
{
    return t + sum(u...);
}


void variadic()
{ 
    cout << sum(1, 2, 3, 4) << endl;
}

int main()
{
    //consuming_templates();
    //template_functions();
    variadic();
    getchar();
    return 0;
}

error:

Severity    Code    Description Project File    Line    Suppression State
Error   C2672    'sum': no matching overloaded function found   Templates

Severity    Code    Description Project File    Line    Suppression State
Error   C2893    Failed to specialize function template 'unknown-type sum(T,U...)'  Templates   

Severity    Code    Description Project File    Line    Suppression State
Error   C2780    'T sum(T)': expects 1 arguments - 4 provided   Templates   C:\Users\erind\source\repos\Templates\Templates\Templates.cpp   35  

Solution

  • It's a works for std::common_type.

    I mean... try rewriting your sum() variadic version as follows

    template<typename T, typename ...U>
    auto sum(T t, U ...u) -> typename std::common_type<T, U...>::type
    {
        return t + sum(u...);
    }
    

    The problem in your code is that with

    template<typename T, typename ...U>
    auto sum(T t, U ...u) -> decltype(t + sum(u...))
    {
        return t + sum(u...);
    }
    

    you try to set the return type recursively with decltype(t + sum(u...)) but doesn't works.

    Starting from C++14, you can simply use auto, without trailing return type

    template<typename T, typename ...U>
    auto sum(T t, U ...u)
    {
        return t + sum(u...);
    }
    

    Starting from C++17, you can use template folding and avoid recursion at all

    template <typename ... U>
    auto sum (U ... u)
     { return (u + ...); }