2

I am trying to make a simple implementation of the std::function

The following code works with function pointers and lambdas which are explicitly converted.

template<typename funct>
class functor {
private:
    funct *function;
public:
    functor() = default;
    functor(funct *func) : function(func) {};

    template<typename T>
    T operator()(T a, T b){
        return function(a, b);
    }
};

int add(int a, int b) {
    return a + b;
}
int main(int argc, char **argv) {
    std::map<std::string, functor<int(int,int)>> maps = { {"+", add} };
    maps.insert({ "%", {[](int i, int j)->int { return i * j; } } } );
    auto temp = maps["%"](5,6);
    std::cout << temp << std::endl;
    system("PAUSE");
    return 0;
 }

I want to know why lambdas don't work with implicit conversion.

maps.insert({ "%", [](int i, int j)->int { return i * j; } }  );

The above code doesn't work but the following does:

maps.insert({ "%", {[](int i, int j)->int { return i * j; } } } );

but the std::function works with {} and without.

Garf365
  • 3,619
  • 5
  • 29
  • 41
ambli
  • 25
  • 4
  • 1
    `std::function` has a templated constructor. – Kerrek SB Aug 30 '16 at 12:40
  • @KerrekSB Speaks wisdom.....having a templated constructor could allow you to do what you are trying to do.....that said I don't know how `std::function` accomplishes the same goals. – DarthRubik Aug 30 '16 at 12:42
  • Another thing to consider is lambdas are not function objects. You may convert a lambda into a function object but they are different and this also may be an intentional reason why there is no implicit conversion. Also see http://stackoverflow.com/questions/21586756/why-doesnt-c11-implicitly-convert-lambdas-to-stdfunction-objects – Hayt Aug 30 '16 at 12:46
  • Try `maps.emplace("%", [](int i, int j)->int { return i * j; });`. – D Drmmr Aug 30 '16 at 12:59

1 Answers1

2

As @KerrekSB mentioned in the comments, just give your functor a templated constructor like this:

template<class F>
functor(F f) : function(f) {}

Now you can omit the braces when initializing the map:

#include <map>
#include <iostream>

template<typename funct>
class functor {
private:
    funct *function;
public:
    functor() = default;

    template<class F>
    functor(F f) : function(f) {}

    template<typename T>
    T operator()(T a, T b){
        return function(a, b);
    }
};

int add(int a, int b) {
    return a + b;
}

int main(int argc, char **argv) {
    std::map<std::string, functor<int(int,int)>> maps = { {"+", add} };
    maps.insert({ "%", [](int i, int j)->int { return i * j; } }  );
    auto temp = maps["%"](5,6);
    std::cout << temp << std::endl;
 }

Live Example

TemplateRex
  • 69,038
  • 19
  • 164
  • 304