使用std :: function参数

时间:2016-08-28 21:27:00

标签: c++ c++11 lambda operator-overloading overloading

我正在研究多种类型的地图持有者。它适用于所有原始类型,也适用于结构,例如点。但是,如果我想将std :: function添加为另一个受支持的类型(用于回调),那么编译器会抱怨:

  

MT.cpp:426:15:没有可行的重载'='

     

MT.h:31:7:候选功能   (隐式复制赋值运算符)不可行:不知道   从'(lambda at MT.cpp:426:17)'转换为'const sharkLib :: MT'   第一个参数

     

MT.h:31:7:候选函数(隐含的举动   赋值运算符)不可行:没有已知的转换''(lambda at   MT.cpp:426:17)'to'sharkLib :: MT'代表第一个参数

我实际上并不重载=运算符,而是使用每个受支持类型的专用构造函数重载[]

·H

protected: 
    map<string,MT> valueMap;

public:
    MT (int value);
    MT (std::function<void(Ref*)> ccb);
    virtual MT& operator[] (const char* key);

的.cpp

MT::MT (int value)
{
    this->type = ValueType::intValue;
    this->value.int_ = value;
}

MT::MT (std::function<void(Ref*)> value)
{
    this->type = ValueType::ccbValue;
    this->value.ccb_ = value;
}

MT& MT::operator[] (const char* key)
{
    return this->valueMap[key];
}

使用

MT mt;

mt["int"] = 1;
mt["ccb"] = [](Ref *){ CCLOG("Pressed"); };

最后一行是错误的。

2 个答案:

答案 0 :(得分:4)

问题是您正在尝试使用双转换序列:

  1. 从lambda函数到std::function<void(Ref*)>
  2. std::function<void(Ref*)>MT
  3. 接下来就是使用

    来消除双重转换的需要
    mt["cast via function"] = static_cast<std::function<void(Ref*)>([](Ref*){ /*...*/ });
    mt["cast via MT"] = MT([](Ref*){ /*...*/ });
    

    如果要支持从函数类型到MT的转换,则需要一个MT的构造函数,它直接采用函数类型。假设您的其他构造函数都没有使用无约束模板编写,您只需添加

    即可
    template <typename Fun>
    MT::MT(Fun&& fun)
        : type(ValueType::ccbValue) {
        this->value.ccb = std::forward<Fun>(fun);
    }
    

    如果您已经将非约束模板用于其他类型,则需要使用合适的条件,例如: std::is_convertible<Fun, std::function<void(Ref*)>>::value,以及合适的SFINAE方法,从过载集中删除相应的构造函数。

答案 1 :(得分:2)

好的,克里斯启发了我,这就是解决方案:

typedef std::function<void(Ref*)> ClickCallback;
...
    MT (ClickCallback ccb);
...
mt["ccb"] = (ClickCallback) [](Ref *){ CCLOG("Pressed "); };;