8

Taken from cppreference, why does the call to std::apply(add_generic, ...) fail to compile? Is there a way to fix it?

#include <iostream>
#include <tuple>

int add(int first, int second)
{
    return first + second;    
}

template<typename T>
T add_generic(T first, T second)
{
    return first + second;    
}

int main()
{
    std::cout << std::apply(add, std::make_tuple(1,2)) << '\n';

    // template argument deduction/substitution fails
    std::cout << std::apply(add_generic, std::make_tuple(2.0f,3.0f)) << '\n'; 
}

It fails with error:

[x86-64 gcc 7 (snapshot)] error: no matching function for call to 'apply(, std::tuple)' [x86-64 gcc 7 (snapshot)] note: couldn't deduce template parameter '_Fn'

4
  • Without seeing what errors you get, I would guess it's could be because of not being able to properly deduce the argument type T? Commented Apr 2, 2017 at 17:30
  • How are you compiling the code? std::apply requires c++17, does your compiler have c++17 support? Commented Apr 2, 2017 at 17:33
  • 3
    add_generic isn't a function, it's a template. You can't deduce a type from something that doesn't have a type. Commented Apr 2, 2017 at 17:36
  • 2
    @Rogus Given the fact that the OP specifically included that only the call involving add_generic fails, I think it's safe to say the OP is using a C++17 compiler+library (or something sufficiently close for the purposes of this question). Commented Apr 2, 2017 at 17:36

1 Answer 1

15

This is not new in C++17. Just from the signature of std::apply, there is no telling whether you want to pass add_generic<int>, add_generic<float>, add_generic<std::string>, or anything else. Knowing that requires more context (specifically: it requires knowing how std::apply is going to invoke it), but that information isn't available at the call site and so cannot be used for template argument deduction.

It's possible to work around that by passing one object, and making that one object capable of calling whichever instantiation of add_generic is needed:

std::cout << std::apply(
    [](auto first, auto second) { return add_generic(first, second); },
    std::make_tuple(2.0f,3.0f)) << '\n';
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.