0

I am trying to create a std::map that has an integer as the key and a function as the value. When I try to insert a value, either via = or insert(), I get the following error:

Error C2207 'std::pair<_Ty1,_Ty2>::second': a member of a class template cannot acquire a function type

Here is the sample code:

std::map<int, std::function<void()>> myMap;
myMap[0] = [] {std::cout << "zero\n"; };
myMap.insert(std::make_pair<int, std::function<void()> >(0, [] {std::cout << "zero\n";} ) ) 

Why can't I do this, and how do I fix it?

8
  • 3
    Apart from anything else you appear to have a typo: std::function<void>() --> std::function<void()> in the declaration of myMap. Commented Oct 15, 2022 at 15:41
  • 5
    @273K ??????????? Commented Oct 15, 2022 at 15:48
  • @273K They can use whatever they want. The system is clever, when I type @ it suggests πάνταῥεῖ (only), because they're the only commenter here with unprintable characters in the name. On the other hand, when I do @H (cyrillic Н on a cyrillic keyboard), I don't get any suggestion, because you're not supposed to @ the OP. Commented Oct 15, 2022 at 15:52
  • @НиколаХилендаров Please undo your last edit. Editing the question in a way that renders existing comments/answers obsolete is counterproductive. Commented Oct 15, 2022 at 15:57
  • 1
    It is a mistake to explicitly specify the template parameters of std::make_pair(), always let it deduce the parameters. Commented Oct 15, 2022 at 18:34

1 Answer 1

2

A lambda is not a std::function, so you need to do a bit more work. Usually I have a class with a map as member and a function template that allows to add lambda. Here is some code without such a wrapper.

Note that initializing at construction is by far the easiest way to do it. Then the constructor of std::function<void()> is called with the lambda (which is fine).

#include <functional>
#include <map>
#include <iostream>

template<typename fn_t>
auto to_fn(fn_t&& fn)
{
    return std::function<void()>{fn};
}


int main()
{
    std::map<int, std::function<void()>> map
    {
        { 0, [] { std::cout << "0\n"; }}
    };

    // map.insert(1, []{ std::cout << "1\n"; }); a lambda is not a function

    map.insert({ 1, std::function<void()>{ [] { std::cout << "1\n"; } } });
    map.insert({ 2, to_fn([] { std::cout << "2\n"; }) });


    map[2]();
    
    return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you for your answer, but for some reason this is not working for me. I am getting this error "Error C2207 'std::pair<_Ty1,_Ty2>::second': a member of a class template cannot acquire a function type" I guess it might be compiler specific.
Could be clang/gcc and msvc I tested don't seem to have that problem. e.g. clang : godbolt.org/z/v6zbhj5jr

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.