C++ c++;带有派生类的模板专门化
我在尝试专门化类的模板方法以接受派生类时遇到问题。我也尝试过使用指针,但最终遇到的问题比这次迭代多得多C++ c++;带有派生类的模板专门化,c++,templates,C++,Templates,我在尝试专门化类的模板方法以接受派生类时遇到问题。我也尝试过使用指针,但最终遇到的问题比这次迭代多得多 #include <iostream> using namespace std; class Json { public: Json(){} virtual ~Json(){} template <class T> bool Get(std::string key, T& value); }; template <
#include <iostream>
using namespace std;
class Json {
public:
Json(){}
virtual ~Json(){}
template <class T>
bool Get(std::string key, T& value);
};
template <class T>
bool Json::Get(std::string key, T& value){
std::cout << "Call default GET" << std::endl;
}
template <>
bool Json::Get(std::string key, Json& value){
std::cout << "Call JSON GET" << std::endl;
}
class JsonError : public Json {
public:
JsonError(){}
~JsonError(){}
};
int main()
{
// OK
int int_value = 0;
Json json;
json.Get("int", int_value);
// OK
Json json_value;
json.Get("json", json_value);
// NOT OK
JsonError json_error_value;
json.Get("error", json_error_value);
return 0;
}
模板不是这样工作的。模板推断总是精确的类型,在本例中是
JsonError
,因此Json&
的专门化不匹配
如果您仍然想让它工作,您可以使用一个成员函数重载模板函数,该函数采用Json&
。对于派生类型,模板函数仍然是一个更好的匹配,因此我们还需要对从Json
派生的任何类型禁用模板方法
#include <iostream>
class Json {
public:
Json(){}
virtual ~Json(){}
template <class T, std::enable_if_t<!std::is_base_of_v<Json, T>, int> = 0>
bool Get(std::string key, T& value);
bool Get(std::string key, Json& value);
};
template <class T, std::enable_if_t<!std::is_base_of_v<Json, T>, int> = 0>
bool Json::Get(std::string key, T& value){
std::cout << "Call default GET" << std::endl;
return true;
}
bool Json::Get(std::string key, Json& value){
std::cout << "Call JSON GET" << std::endl;
return true;
}
class JsonError : public Json {
public:
JsonError(){}
~JsonError(){}
};
int main()
{
// OK
int int_value = 0;
Json json;
json.Get("int", int_value);
// OK
Json json_value;
json.Get("json", json_value);
// NOW IT'S OK
JsonError json_error_value;
json.Get("error", json_error_value);
return 0;
}
#包括
类Json{
公众:
Json(){}
虚拟~Json(){}
模板=0>
bool-Get(标准::字符串键,T和值);
bool-Get(std::字符串键、Json和值);
};
模板=0>
booljson::Get(std::字符串键、T和值){
std::cout模板类型推断的参数总是比需要任何隐式强制转换的参数更精确(例如JsonError&
到Json&
),因此在重载解析过程中总是会被解析为更好的重载。您可以解决这一问题,但重新思考所需的APICannot REPLACTION可能会更容易:您使用的是什么编译器和版本?@人工编译器在这里没有出现。t
被推断为JsonError
,这意味着n forJson
不被使用,默认模板被调用,至少在一致性编译器中是这样。@NathanOliver我认为OP意味着所需的输出是Json GET
,但程序不是这样做的。@NathanOliver OP希望最后一次调用打印call Json GET
,没有错误,但最后一次调用的当前输出是正确的是Call default GET
我没有访问C++11的权限,但这是一个很酷的答案。@ony_pox232实际上asnwer中的代码使用C++17,但在C++11中没有不能完成的操作。对于与当前标准无关的问题,最好使用该标准特定版本的标记
#include <iostream>
class Json {
public:
Json(){}
virtual ~Json(){}
template <class T, std::enable_if_t<!std::is_base_of_v<Json, T>, int> = 0>
bool Get(std::string key, T& value);
bool Get(std::string key, Json& value);
};
template <class T, std::enable_if_t<!std::is_base_of_v<Json, T>, int> = 0>
bool Json::Get(std::string key, T& value){
std::cout << "Call default GET" << std::endl;
return true;
}
bool Json::Get(std::string key, Json& value){
std::cout << "Call JSON GET" << std::endl;
return true;
}
class JsonError : public Json {
public:
JsonError(){}
~JsonError(){}
};
int main()
{
// OK
int int_value = 0;
Json json;
json.Get("int", int_value);
// OK
Json json_value;
json.Get("json", json_value);
// NOW IT'S OK
JsonError json_error_value;
json.Get("error", json_error_value);
return 0;
}