I'm working on Multi-type map holder. It works with all primitive types and also with structs e.g. Point. However, if I want to add std::function as another supported type (used for callbacks) then the compiler complains:
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
I don't actually overload =
operator but instead overload []
with dedicated constructor per supported type.
.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];
}
usage
MT mt;
mt["int"] = 1;
mt["ccb"] = [](Ref *){ CCLOG("Pressed"); };
This last line is the one with error.
The problem is that you are trying to use a double conversion sequence:
std::function<void(Ref*)>
std::function<void(Ref*)>
to MT
On way around that is to remove the need of the double conversion, using either
mt["cast via function"] = static_cast<std::function<void(Ref*)>([](Ref*){ /*...*/ });
mt["cast via MT"] = MT([](Ref*){ /*...*/ });
If you want to support the conversion from a function type to MT
you'd need a constructor of MT
which directly takes the function type. Assuming none of your other constructors is written with using an unconstrained template, you could just add
template <typename Fun>
MT::MT(Fun&& fun)
: type(ValueType::ccbValue) {
this->value.ccb = std::forward<Fun>(fun);
}
If you are already using an unconstrained template for another type you'd need to use suitable conditions, e.g. std::is_convertible<Fun, std::function<void(Ref*)>>::value
, together with a suitable SFINAE-approach to remove the respective constructor(s) from the overload set.
Ok, Chris inspired me and this is the solution:
typedef std::function<void(Ref*)> ClickCallback;
...
MT (ClickCallback ccb);
...
mt["ccb"] = (ClickCallback) [](Ref *){ CCLOG("Pressed "); };;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With