带有 std::function 参数的重载运算符
overloaded operator with std::function parameter
我正在研究多类型地图架。它适用于所有原始类型以及结构,例如观点。但是,如果我想添加 std::function 作为另一个支持的类型(用于回调),那么编译器会抱怨:
MT.cpp:426:15: No viable overloaded '='
MT.h:31:7: Candidate function
(the implicit copy assignment operator) not viable: no known
conversion from '(lambda at MT.cpp:426:17)' to 'const sharkLib::MT'
for 1st argument
MT.h:31:7: Candidate function (the implicit move
assignment operator) not viable: no known conversion from '(lambda at
MT.cpp:426:17)' to 'sharkLib::MT' for 1st argument
我实际上并没有重载 =
运算符,而是使用每个支持的类型的专用构造函数重载 []
。
.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"); };
最后一行有错误。
好的,克里斯启发了我,这就是解决方案:
typedef std::function<void(Ref*)> ClickCallback;
...
MT (ClickCallback ccb);
...
mt["ccb"] = (ClickCallback) [](Ref *){ CCLOG("Pressed "); };;
问题是您正在尝试使用双重转换序列:
- 从 lambda 函数到
std::function<void(Ref*)>
- 从
std::function<void(Ref*)>
到 MT
解决这个问题的方法是使用任一
消除双重转换的需要
mt["cast via function"] = static_cast<std::function<void(Ref*)>([](Ref*){ /*...*/ });
mt["cast via MT"] = MT([](Ref*){ /*...*/ });
如果你想支持从函数类型到 MT
的转换,你需要一个直接采用函数类型的 MT
的构造函数。假设你的其他构造函数 none 是使用不受约束的模板编写的,你可以只添加
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 方法从重载集中删除相应的构造函数。
我正在研究多类型地图架。它适用于所有原始类型以及结构,例如观点。但是,如果我想添加 std::function 作为另一个支持的类型(用于回调),那么编译器会抱怨:
MT.cpp:426:15: No viable overloaded '='
MT.h:31:7: Candidate function (the implicit copy assignment operator) not viable: no known conversion from '(lambda at MT.cpp:426:17)' to 'const sharkLib::MT' for 1st argument
MT.h:31:7: Candidate function (the implicit move assignment operator) not viable: no known conversion from '(lambda at MT.cpp:426:17)' to 'sharkLib::MT' for 1st argument
我实际上并没有重载 =
运算符,而是使用每个支持的类型的专用构造函数重载 []
。
.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"); };
最后一行有错误。
好的,克里斯启发了我,这就是解决方案:
typedef std::function<void(Ref*)> ClickCallback;
...
MT (ClickCallback ccb);
...
mt["ccb"] = (ClickCallback) [](Ref *){ CCLOG("Pressed "); };;
问题是您正在尝试使用双重转换序列:
- 从 lambda 函数到
std::function<void(Ref*)>
- 从
std::function<void(Ref*)>
到MT
解决这个问题的方法是使用任一
消除双重转换的需要mt["cast via function"] = static_cast<std::function<void(Ref*)>([](Ref*){ /*...*/ });
mt["cast via MT"] = MT([](Ref*){ /*...*/ });
如果你想支持从函数类型到 MT
的转换,你需要一个直接采用函数类型的 MT
的构造函数。假设你的其他构造函数 none 是使用不受约束的模板编写的,你可以只添加
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 方法从重载集中删除相应的构造函数。