我的模板 class 的构造函数将可调用对象作为参数但无法从中初始化?

My template class's ctor takes a callable object as an argument but cannot be initialized from it?

有人要求我通过函数 table 使用 std::function 实现桌面计算器,仅适用于二元运算符。所以我有这个代码:

#include <functional>
#include <iostream>
#include <string>

int main()
{
    std::map<std::string, std::function<int(int, int)>> binOp;
    binOp["+"] = [](int a, int b){return a + b;};
    binOp["*"] = [](int a, int b){return a * b;};

    binOp["-"] = [](int a, int b){return a - b;};

    binOp["/"] = [](int a, int b){return a / b;};

    binOp["%"] = [](int a, int b){return a % b;};

    for(const auto& p : binOp)
        std::cout << 9 << " " << p.first << " " << 8 << " = " << p.second(9, 8) << std::endl;

}

* 该程序适用于整数操作数的二元运算符。我想使我的 class 模板成为通用的,它可以处理不同类型的操作数 int, double, std::string... 所以我在 decltype:

的帮助下自己尝试了这个
template <typename T>
struct BinOp
{
    BinOp() = default;
    BinOp(T f) : fn(f){}
    std::function<T> fn;
    using arg_type = decltype(fn(0, 0));
    arg_type operator()(arg_type a, arg_type b){return fn(a, b);}
};


int main()
{

    std::map<std::string, BinOp<int(int, int)>> calc;
    calc["+"] = BinOp<int(int, int)>([](int x, int y){return x + y;});
    calc["*"] = BinOp<int(int, int)>([](int x, int y){return x * y;});
    calc["-"] = BinOp<int(int, int)>([](int x, int y){return x - y;});
    calc["/"] = BinOp<int(int, int)>([](int x, int y){return x / y;});
    calc["%"] = BinOp<int(int, int)>([](int x, int y){return x % y;});

    for(const auto& e : calc)
        std::cout << 10 << " " << e.first << " " << 12 <<
        " = " << e.second(10, 12) << endl;

    //BinOp<std::string(std::string, std::string)> bstr = [](string s1, string s2){return s1 + s2;}; // it doesn't work?

    BinOp<std::string(std::string, std::string)> bstr;
    bstr.fn = [](string s1, string s2){return s1 + s2;}; // works fine!

    std::cout << bstr("Hello ", "Wold!") << std::endl;


    std::cout << "\nDone!\n";
}

这里可以使用直接初始化直接构造一个BinOp

BinOp<std::string(std::string, std::string)> bstr {[](string s1, string s2){return s1 + s2;}};

您的原始代码无法编译的原因可能是因为您要求编译器执行两次转换,但它不会执行。