#c #visual-studio #cocos2d-x #sfinae
#c #visual-studio #cocos2d-x #sfinae
Вопрос:
Я создаю игру, в которую можно играть на Mac и Windows с помощью cocos2d-x.
Сначала я написал код в Xcode, который можно было запускать на Mac.
Я получил сообщение об ошибке, когда перенес его в Windows и попытался выполнить сборку в 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::stringamp; getName(){return _name;}
cocos2d::Ref* getSender(){return _sender;}
NRZNotification();
virtual ~NRZNotification();
static NRZNotification* create(const std::stringamp; name, Ref* sender);
bool init(const std::stringamp; 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::stringamp; 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::stringamp; 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::stringamp; key)
{
if (_valueMap.find(key) == _valueMap.end()) {
return 0;
} else {
return _valueMap.at(key).asInt();
}
}
template <>
inline float NRZNotification::getValue(const std::stringamp; key)
{
if (_valueMap.find(key) == _valueMap.end()) {
return 0.0f;
} else {
return _valueMap.at(key).asFloat();
}
}
template <>
inline double NRZNotification::getValue(const std::stringamp; key)
{
if (_valueMap.find(key) == _valueMap.end()) {
return 0.0;
} else {
return _valueMap.at(key).asDouble();
}
}
...
Эти коды успешно выполнялись на Mac, но в Visual Studio 2017 вызов GetValue() выдал ошибку «не может быть явно специализирован».
GetValue() — это шаблон функции, и реализация разделяется в зависимости от того, является ли возвращаемое значение подклассом cocos2d::Ref .
Кроме того, специализация выполняется для int, float, string и т. Д.
Как я должен исправить этот код?
Я использую cocos2d-x 3.17.1.
Спасибо.
Комментарии:
1. Показать ошибку компилятора.
Ответ №1:
Я взял на себя смелость создать MCVE на основе вашего кода.
#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>();
}
Действительно, MSVC 2019 не может его скомпилировать
<source>(15): error C2910: 'A::getValue': cannot be explicitly specialized
В то время как GCC и clang компилируют его просто отлично. Живая демонстрация.
К счастью, решение простое — просто удалите явные параметры шаблона. В любом случае они излишни:
template<>
inline int A::getValue() {
return 3;
}
Итак, для вашего случая удалите <int,nullptr>
из
template <>
inline int NRZNotification::getValue<int,nullptr>(const std::stringamp; key)