Search code examples
c++c++14

error: no matching function for call to 'std::tuple<std::vector<int, std::allocator<int> >&, int>::tuple()'


Hey I normally work with Javascript and dart but I've been required to write some code in C++ for some project so I've been facing a lot of issues while writing it. I have this error that I've been trying to solve for hours with no clue I've finally decided to come here for help.

First I have this generic function that can create a tuple out of the params of the function passed into it as an argument.

template <typename R, typename... T>
tuple<T...> function_args(R (*)(T...))
{
    return tuple<T...>();
}

But whenever i pass it a function that takes a vector as an argument it ends throwing an error

/tmp/ViPPynah0U.cpp: In instantiation of 'void function_args(R (*)(T ...)) [with R = int; T = {std::vector<int, std::allocator<int> >&, int}]':
/tmp/ViPPynah0U.cpp:33:18:   required from here
/tmp/ViPPynah0U.cpp:23:17: error: no matching function for call to 'std::tuple<std::vector<int, std::allocator<int> >&, int>::tuple()'

And here is the complete sample code for further clarification,

#include <iostream>
#include <sstream>
#include <string>
#include <tuple>
#include <vector>

using namespace std;

int example(vector<int> &nums, int target)
    {
        return 0;
    }

template <typename R, typename... T>
tuple<T...> function_args(R (*)(T...))
{
    return tuple<T...>();
}

int main(int argc, char const *argv[])
{
    auto params = function_args(example);
    return 0;
}

As I've already mentioned the function works when I pass it a function that takes only primitive types as arguments the error only happens when the function takes in a vector


Solution

  • The issue is not with the vector, but with the fact that the function takes it as reference. You then try to initialize a tuple with a reference element here: return tuple<T...>(); - and that's not going to work. The error message basically says that: There is no default constructor for std::tuple<std::vector<int>&,int>.

    Depending on what you want to do in that case you could for example remove the reference-ness from the Ts:

    template <typename R, typename... T>
    auto function_args(R (*)(T...))
    {
        return tuple<std::remove_reference_t<T>...>();
    }
    

    Live Demo