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?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 3
    Apart from anything else you appear to have a typo: `std::function()` --> `std::function` in the declaration of `myMap`. – G.M. Oct 15 '22 at 15:41
  • 5
    @273K ??????????? – πάντα ῥεῖ Oct 15 '22 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. – HolyBlackCat Oct 15 '22 at 15:52
  • @НиколаХилендаров Please undo your last edit. Editing the question in a way that renders existing comments/answers obsolete is counterproductive. – G.M. Oct 15 '22 at 15:57
  • (1) add a semicolon at the end of the 3rd line. (2) insert into a different key position. (3) use emplace `myMap.emplace(1, [] {std::cout << "xero\n";}) ;` – QuentinUK Oct 15 '22 at 16:02
  • @HolyBlackCat You are not completely right. НиколаХилендаров is suggested after his comment although he is the OP. πάνταῥεῖ is suggested too. But your nickname is not suggested until H is typed. The single @ seems to start with competition of non ASCII nicknames only. – 273K Oct 15 '22 at 16:59
  • [Can't reproduce](https://godbolt.org/z/ojWrq6M91). – n. m. could be an AI Oct 15 '22 at 17:35
  • 1
    It is a [mistake to explicitly specify the template parameters of `std::make_pair()`](https://stackoverflow.com/questions/9641960/), always let it deduce the parameters. – Remy Lebeau Oct 15 '22 at 18:34

1 Answers1

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;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19
  • 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. – Никола Хилендаров Oct 16 '22 at 14:46
  • Could be clang/gcc and msvc I tested don't seem to have that problem. e.g. clang : https://godbolt.org/z/v6zbhj5jr – Pepijn Kramer Oct 16 '22 at 14:49