специализировать только (часть) одного метода класса шаблона

Если у меня есть класс шаблона

template<typename T>
class C {
public:
    void method1() { ... }
    void method2() { ... }
    std::string method3(T &t) {
        // ...
        std::string s = t.SerializeToString();
        // ...
        return s;
    }
    // ...
};

и я хочу специализировать его для T = std::string, но только изменив method3(T&) (сохранив все остальные методы), а еще лучше, только ту часть метода3, которая для T = std::string просто станет std::string s = t;, с минимальным влиянием на текущий код (меньше повторения сигнатур методов, меньше подклассов), как бы я это сделал?

РЕДАКТИРОВАТЬ: я разрабатываю на С++ 11


person fferri    schedule 31.10.2017    source источник


Ответы (2)


Вы можете использовать такую ​​специализацию (не нужно специализировать весь класс):

template<>
std::string C<string>::method3(string &t) {
    // ...
    std::string s = t;
    // ...
    return s;
}
person Jarod42    schedule 31.10.2017
comment
Я разместил минимальный пример, но на самом деле мне нужно специализировать весь класс - person fferri; 31.10.2017
comment
@fferri: в вашем заголовке буквально написано специализировать только (часть) одного метода класса шаблона. - person Vittorio Romeo; 31.10.2017
comment
@ Jarod42: вы предлагаете удалить параметр шаблона для класса? Или я неправильно понял ваш ответ. - person fferri; 31.10.2017
comment
@fferri это называется функцией шаблона. - person UKMonkey; 31.10.2017
comment
@fferri: Если вы специализируетесь на всем классе, вам также нужно переписать method1/method2. Вы можете (полностью) специализироваться только на данном методе. класс по-прежнему является шаблоном, а метод — нет. - person Jarod42; 31.10.2017

Если вам нужно изменить только инициализацию s, вы можете использовать перегрузку:

std::string init(std::string& t)
{
    return t;
}

template <typename T>
std::string init(T& t)
{
    return t.SerializeToString();
}

template <typename T>    
std::string method3(T &t) {
    // ...
    std::string s = init(t);
    // ...
    return s;
}

В С++ 17 вы можете использовать if constexpr:

std::string method3(T &t) 
{
    if constexpr(std::is_same_v<T, std::string>)
    {
        std::string s = t;
        // ...
        return s;
    }
    else
    {
        std::string s = t.SerializeToString();
        // ...
        return s;
    }
}

В C++14 вы можете использовать static_if:

std::string method3(T &t) 
{
    static_if(std::is_same<T, std::string>{})
    .then([](auto& x)
    {
        std::string s = x;
        // ...
        return x;
    })
    .else_([](auto& x)
    {
        std::string s = x.SerializeToString();
        // ...
        return x;
    })(t);
}
person Vittorio Romeo    schedule 31.10.2017