I am making a game playable on mac and windows with cocos2d-x.
I first wrote the code in Xcode, which could be run on mac.
I got an error when I took it to Windows and tried to build in Visual Studio 2017.
NRZNotification.h
#include "cocos2d.h"
class NRZNotification : public cocos2d::Ref
{
protected:
std::string _name;
cocos2d::Ref* _sender;
...
cocos2d::ValueMap _valueMap;
cocos2d::Map<std::string, cocos2d::Ref*> _objectMap;
public:
const std::string& getName(){return _name;}
cocos2d::Ref* getSender(){return _sender;}
NRZNotification();
virtual ~NRZNotification();
static NRZNotification* create(const std::string& name, Ref* sender);
bool init(const std::string& name, Ref* sender);
...
template <typename T,
typename std::enable_if<!std::is_convertible<T, cocos2d::Ref*>::value,
std::nullptr_t>::type = nullptr>
inline T getValue(const std::string& key)
{
//CCLOG("%s", __PRETTY_FUNCTION__);
return 0;
}
template <typename T,
typename std::enable_if<std::is_convertible<T, cocos2d::Ref*>::value,
std::nullptr_t>::type = nullptr>
inline T getValue(const std::string& key)
{
//CCLOG("%s", __PRETTY_FUNCTION__);
return dynamic_cast<T>(_objectMap.at(key));
}
};
#include "NRZNotification_Private.h"
NRZNotification_Private.h
#include "NRZNotification.h"
...
#pragma mark - get value
template <>
inline int NRZNotification::getValue<int,nullptr>(const std::string& key)
{
if (_valueMap.find(key) == _valueMap.end()) {
return 0;
} else {
return _valueMap.at(key).asInt();
}
}
template <>
inline float NRZNotification::getValue(const std::string& key)
{
if (_valueMap.find(key) == _valueMap.end()) {
return 0.0f;
} else {
return _valueMap.at(key).asFloat();
}
}
template <>
inline double NRZNotification::getValue(const std::string& key)
{
if (_valueMap.find(key) == _valueMap.end()) {
return 0.0;
} else {
return _valueMap.at(key).asDouble();
}
}
...
These codes ran successfully on mac, but in Visual Studio 2017, calling getValue() gave the error "cannot be explicitly specialized".
getValue() is a function template, and the implementation is divided according to whether the return value is a subclass of cocos2d::Ref.
Furthermore, specialization is done for int, float, string, etc.
How should I fix this code?
I am using cocos2d-x 3.17.1.
Thank you.
I took the liberty to create a MCVE from your code.
#include <type_traits>
struct A {
template<typename T, typename std::enable_if<!std::is_convertible<T, A>::value, int>::type = 0>
T getValue() {
return 1;
}
template<typename T, typename std::enable_if<std::is_convertible<T, A>::value, int>::type = 0>
T getValue() {
return T();
}
};
template<>
inline int A::getValue<int, 0>() {
return 3;
}
int main() {
A a;
return a.getValue<int>();
}
Indeed, MSVC 2019 fails to compile it
<source>(15): error C2910: 'A::getValue': cannot be explicitly specialized
Whereas GCC and clang compile it just fine. Live demo.
Fortunately the solution is simple - just remove the explicit template parameters. They are superfluous anyway:
template<>
inline int A::getValue() {
return 3;
}
So for your case remove <int,nullptr>
from
template <>
inline int NRZNotification::getValue<int,nullptr>(const std::string& key)