Как использовать производный тип в специализации шаблона функции возвращаемого типа?(«Не удалось определить аргумент шаблона») - PullRequest
0 голосов
/ 02 января 2019

У меня есть шаблонный класс и функция с типом возвращаемого шаблона:

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). Итак, это можно сделать? Что не так с подходом выше?

1 Ответ

0 голосов
/ 02 января 2019

Компилятор уже сказал вам, в чем проблема:

примечание: шаблон кандидата игнорируется: невозможно определить аргумент шаблона 'T'

Вам необходимо явно указать параметр шаблона.

template <>
typename ReturnType<Foo>::type build_wrapped<Foo>()
{ //                                        ^~~~~
    Foo t{};
    return typename ReturnType<Foo>::type(t);
}
...