У меня есть шаблонный класс и функция с типом возвращаемого шаблона:
template<typename T>
class Wrapper {
public:
Wrapper(const T& _data) : data(_data) { }
const T& get_data() {return data;};
private:
T data;
};
template <typename T>
Wrapper<T> build_wrapped(){
T t{};
return Wrapper<T>(t);
}
Предположим, что я хочу расширить возвращаемое Wrapper
для одного конкретного типа T
и специализировать функцию build_wrapped()
для этого типа. Итак, давайте создадим шаблон для хранения возвращаемого типа и используем его в build_wrapped()
:
template<typename T>
struct ReturnType {
using type = Wrapper<T>;
};
template <typename T>
typename ReturnType<T>::type build_wrapped(){
T t{};
return typename ReturnType<T>::type(t);
}
И используйте его для предоставления специализации:
struct Foo{};
class ExtendedWrapper : public Wrapper<Foo> {
public:
ExtendedWrapper(const Foo& _data) : Wrapper(_data) {}
int get_answer() {return 42;};
};
template<>
struct ReturnType<Foo> {
using type = ExtendedWrapper;
};
template<>
typename ReturnType<Foo>::type build_wrapped(){
Foo t{};
return typename ReturnType<Foo>::type(t);
}
Однако, окончательное объявление отклоняется как gcc, так и clang. Например, clang возвращает:
ошибка: шаблон функции не соответствует специализации шаблона функции
'Build_wrapped'
примечание: шаблон кандидата игнорируется: невозможно определить аргумент шаблона 'T'
Я могу обойтись, используя ReturnType
, создав явную специализацию Wrapper
для Foo
. Однако это требует дублирования всего кода в Wrapper
(в моем случае это существенный класс), когда я просто хочу добавить некоторые новые функции (как в ExtendedWrapper
). Итак, это можно сделать? Что не так с подходом выше?