Как специализировать метод шаблона в подклассе (c++)?

Я пытаюсь специализировать метод шаблона класса non-template в его подклассе:

// .файл H

class MyWriter {
public:
    template<typename T>
    void test(const T & val) {
        std::cout << val << "n";
    }
};

// .файл cpp

class MyType {
public:
    MyType(int aa, double dd) : a(aa), d(dd) {}
    int a;
    double d;
};

class MyWriterExt : public MyWriter {
public:
    template<> void test(const MyType &val) {
        test(val.a);
        test(val.d);
    }
};

int main() {
    MyWriterExt w;
    w.test(10);
    w.test(9.999);
    w.test(MyType(15, 0.25));
 return 0;
}

но я получаю сообщение об ошибке:

Error 1 **error C2912**: explicit specialization; 
'void MyWriterExt::test(const MyType &)' is not a specialization of a function 
    template testtemplate.cpp 30

как расширить класс MyWriter для поддержки пользовательских классов?

2 ответов


специализация должна выполняться для одного и того же класса не для подкласса, а также вне тела класса:

class MyWriter {
public:
    template<typename T>
    void test(const T & val) {
        std::cout << val << "\n";
    }
};

template<>
void MyWriter::test<MyType>(const MyType & val) {
    test(val.a);
    test(val.d);
}

вам не нужен подкласс для специализации исходного шаблона функции-члена.

также считают перегрузка вместо специализации.


как исправить ошибку компиляции?

Error 1 **error C2912**: explicit specialization; 
 'void MyWriterExt::test(const MyType &)' is not a specialization of
     a function template \testtemplate.cpp 30

если вы хотите "специализацию" шаблонной функции в производном классе, решение (в производном классе):

  • перегрузите шаблонную функцию нормальной функцией для вашего параметра MyType
  • "импортировать" шаблонную функцию в текущий класс (чтобы она не была скрыта перегрузкой)

что дает:

class MyWriterExt : public MyWriter {
public:
/*
    template<> void test(const MyType &val) {
        test(val.a);
        test(val.d);
    }
*/
    using MyWriter::test ;
    void test(const MyType &val) {
        test(val.a);
        test(val.d);
    }

};

как код правильно, что вы хотите сделать?

как расширить класс MyWriter для поддержки пользовательских классов?

теперь, если вы используете MyWriter в качестве расширяемого выходного потока, я не уверен, что наследование является решением. Как уже ответили Вито на свой ответ; вы должны специализировать свою шаблонную функцию для (и снаружи) базового объекта.

как код еще больше правильно, что вы хотите делать?

как расширить класс MyWriter для поддержки пользовательских классов?

лучшим решением было бы следовать соглашению потока C++, то есть использовать функции, не являющиеся друзьями, не являющиеся членами. В вашем случае это было бы что-то вроде:

class MyWriter {
public:
};

template<typename T>
MyWriter & operator << (MyWriter & writer, const T & val) {
    std::cout << val << "\n";
    return writer ;
}

любой может затем "специализировать" вашу выходную функцию без необходимости наследования:

MyWriter & operator << (MyWriter & writer, const MyType & val) {
    writer << val.a << val.d ;
    return writer ;
}

который может быть записан в вашем основном как:

int main() {
    MyWriter w;
    w << 10 << 9.999 << MyType(15, 0.25);
 return 0;
}

который, ИМХО, довольно ясно, чем накопление вызовов функций (пока вы не делаете форматирование, выходные потоки C++ настолько просты в использовании).

(конечно, я предполагаю, что MyWriter сделает больше, чем простое перенаправление на std::cout. Если нет, мой автор бесполезен...)