return型函数模板特化如何使用派生类型? ("couldn't infer template argument")

How to use derived type in specialisation of return-type function template? ("couldn't infer template argument")

我有一个模板 class 和一个带有模板的函数 return 类型:

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);
}

假设我想为一种特定类型 T 扩展 returned Wrapper 并为该类型专门化 build_wrapped() 函数。因此,让我们创建一个模板来保存 return 类型并在 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 returns:

error: no function template matches function template specialization 'build_wrapped'

note: candidate template ignored: couldn't infer template argument 'T'

我可以通过为 Foo 创建 Wrapper 的显式特化来绕过 ReturnType 的使用。然而,这需要复制 Wrapper 中的所有代码(在我的现实生活中,它是一个重要的 class),而我只想添加一些新功能(如 ExtendedWrapper)。那么,这可以做到吗?上面的方法有什么问题?

编译器已经告诉你问题所在:

note: candidate template ignored: couldn't infer template argument 'T'

您需要明确指定模板参数。

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