【问题标题】:How to use derived type in specialisation of return-type function template? ("couldn't infer template argument")如何在返回类型函数模板的特化中使用派生类型? (“无法推断模板参数”)
【发布时间】:2019-01-02 17:26:38
【问题描述】:

我有一个模板类和一个模板返回类型的函数:

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 扩展返回的 Wrapper 并为该类型专门化 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”

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

【问题讨论】:

  • 另一种方法是使用标签,然后使用重载:: template &lt;typename T&gt; struct tag{}; template &lt;typename T&gt; Wrapper&lt;T&gt; build_wrapped(tag&lt;T&gt;) { return Wrapper&lt;T&gt;{{}};} ExtendedWrapper build_wrapped(tag&lt;Foo&gt;) { return ExtendedWrapper{{}};}.

标签: c++ templates template-specialization specialization


【解决方案1】:

编译器已经告诉你问题出在哪里了:

注意:候选模板被忽略:无法推断模板参数“T”

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

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

【讨论】:

  • 好收获!谢谢!
  • @user44168 如果答案解决了您的问题,您应该将其标记为已接受以表明这一点(并给回答的人一些代表),而不仅仅是评论“good catch”。
  • @JesperJuhl 是的,好吧,所以强迫你等到发帖后 10 分钟后你才能接受。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 2017-08-06
相关资源
最近更新 更多