首页 > 解决方案 > c ++模板特化与派生类

问题描述

我在尝试专门化类的模板方法以接受派生类时遇到问题。我也尝试过使用指针,但最终遇到的问题比这次迭代要多得多。

#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;
}

这应该打印出来

Call default GET                                                                                                                                            
Call JSON GET                                                                                                                                               
Call JSON GET  

标签: c++templates

解决方案


这不是模板的工作方式。模板推导总是在确切的类型上,在这种情况下JsonError,所以特化 forJson&不匹配。

如果你仍然想让它工作,你可以用一个成员函数来重载模板函数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;
}

推荐阅读