Уточнение шаблона функции

267
19 декабря 2016, 20:10

Ясного неба!

Читаю учебник по с++. Там есть пример уточнения шаблона класса:

template<typename T> class MyCout
{
    private:
        T data;
    public:
        MyCout(T a): data(a) {};
        void display() {cout << data << endl;};
};
template<> class MyCout<string>
{
    private:
        string data;
    public:
        MyCout(string a): data(a){};
        void display() {cout << data.c_str() << endl;};
};

Я решил поэкспериментировать, и немного укоротить код, сделав шаблон не целого класса, а только функции:

class NewCout
{
    public:
        NewCout(){};
        template<typename T> void display(T a){cout << a << endl;};
        template<> void display<string>(string a){cout << a.c_str() << endl;};
};

Но компилятор выдает ошибку на строке №6: invalid explicit specialization before '>' token.
Что я делаю не так?

И еще вопрос вдогонку: как принято оформлять шаблоны?

Answer 1

C++ запрещает частичную специализацию методов, только шаблоны классов могут быть специализированы. См. стандарт, параграф 14.5.6. Почему именно так было сделано, обсуждается здесь (ворнинг: инглиш лэнгвидж инсайд!).

Судя по всему, автор книги не прав.

Вы можете, однако, перегрузить шаблонный метод (что не то же самое).

Ох, позор мне. Вот это работает:

class C
{
public:
    template<typename T>
    void f(T t);
};
template<typename T>
void C::f(T t)
{
    cout << t << endl;
}
template<>
void C::f<int>(int t)
{
    cout << "(int specialization) " << t << endl;
}

Разобрался. В примере над чертой не частичная, а полная специализация. Частичная специализация всё-таки запрещена, как и говорит спецификация. Пример:

class C
{
public:
    template<typename T>
    void f(T t);
};
template<typename T>
void C::f(T t)
{
    cout << t << endl;
}
template<typename T> // ошибка: function template partial 
void C::f<T*>(T* pt) // specialization ‘f<T*>’ is not allowed
{
    cout << "(pointer specialization) " << *pt << endl;
}
Answer 2

Как вариант вынести специализации вне класса

class NewCout
{
    public:
       NewCout(){};
       template<typename T> void display(T a){cout << a << endl;};
};
template<> void NewCout::display<string>(string a){cout << a.c_str() << endl;};

Не знаю насколько это правильное решение, как по мне вся эта шаблонная магия от лукавого. Тем более что специализация шаблона в таком тривиальном случае и не нужна

class NewCout
{
public:
    NewCout(){};
    template<typename T> void display(T a){cout << a << endl;};
    void display(string a){cout << a << endl;};
};
Answer 3
template<> void display(string a){cout << a.c_str() << endl;};
READ ALSO
Как заполнить массив данными из файла

Как заполнить массив данными из файла

Допустим есть файл со следующим содержанием

286
Не получается войти на FTP сервер

Не получается войти на FTP сервер

Здравствуйте! Пытаюсь написать FTP-клиент, столкнулся с трудностьюЧтобы зайти на ftp://87

266
IT компании для стажировки. [закрыто]

IT компании для стажировки. [закрыто]

Хочу пройти стажировку в более менее серьёзной компании, так как это будет полезно для профессионального роста, в большинстве требуются...

247