【问题标题】:Compiler rejects two identical template specializations编译器拒绝两个相同的模板特化
【发布时间】:2013-03-25 12:50:57
【问题描述】:

我正在使用两个辅助结构来处理智能指针和向量

template<typename T>
struct Pointer {
    typedef shared_ptr<T> type;
};

template<typename T>
struct Vector {
    typedef vector<T, allocator<T>> type;
};

在这种情况下是很明显的表达方式

is_same<
    vector<
        shared_ptr<T>,
        allocator<shared_ptr<T>>>,
    Vector<
        Pointer<T>::type>::type>
::value

为真。但是我现在有一个模板函数(实际上是一个操作符),在使用 Vector&lt;Pointer&lt;T&gt;::type&gt;::type 或通常的 vector 时处理方式不同:

// (1) General version
template<typename T>
Foo& operator&(T& object);

// (2a) Specialized version
template<typename T>
Foo& operator&(vector<shared_ptr<T>, allocator<shared_ptr<T>>>& object);

// (2b) Specialized version which does not work
template<typename T>
Foo& operator&(typename Vector<typename Pointer<T>::type>::type& object);

当我的代码中有 (2a) 时调用此运算符按预期工作。但是,当我将 (2a) 替换为 (2b) 时,编译器/链接器会尝试将调用与 (1) 匹配,这对我来说会产生链接错误,因为 (1) 未定义/对向量有效。为什么编译器对 (2a) 和 (2b) 的处理方式不同?

【问题讨论】:

  • 那些typenames 是2b的必需品吗?
  • 您无需将allocator 模板参数指定给vector。默认情况下,它将与您声明的完全一样。
  • @jt234:IntelliSense 和编译器抱怨没有typenamedependent name is not a type,并建议我使用关键字。

标签: c++ templates stl typedef template-specialization


【解决方案1】:

因为编译器无法推断 (2b) 中的类型。问题是它可以匹配

vector<shared_ptr<T>,allocator<shared_ptr<T>>>

因为那是要匹配的“只是一种类型”。对于任何给定的参数,它只检查是否存在T 并且类型匹配。编译器只需要测试一个选项。对于

typename Vector<typename Pointer<T>::type>::type

编译器必须尝试所有T,而Vector&lt;...&gt;::type 将屈服于所需的类型,但它不会这样做。如果可能的话,这种分析将比仅匹配直接类型复杂得多。

【讨论】:

  • “更复杂”的意思是“需要解决停机问题”(在一般情况下)。您可以通过显式传入 T 类型来解决 OPs 问题。另请注意,此技术(依赖类型参数)用于在许多地方阻止模板类型推导(使用 typename identity&lt;T&gt;::type 参数),以强制调用者显式传递类型。
  • 问题只是我在搜索Vector&lt;Pointer&lt;T&gt;::type&gt;::type 而不是Vector&lt;T&gt;::type?我仍然可以使用最后一个选项,但编译器仍然会抱怨。 - 或者让我们换个问题:绝对没有办法匹配我的辅助结构而不是vectorshared_ptr 的“纯”版本?
  • @ChristianIvicevic:不,问题是带有typename X::typeanything 会阻止推断X,无论它是什么。问题是编译器无法尝试(或分析)哪个X 是正确的。在简单的情况下,您可能会这样看,但没有通用的解决方案,因此标准不允许这样做。
  • 好的,这需要一些时间来适应。
  • @ChristianIvicevic:这个问题叫做non-deducible context,简而言之,我可以做template &lt;&gt; struct Pointer&lt;int&gt; { typedef int type; };template &lt;&gt; struct Pointer&lt;double&gt; { typedef int type; };,现在如果Pointer&lt;T&gt;::type == int,那是什么@987654338 @ ?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-11
  • 1970-01-01
  • 1970-01-01
  • 2021-12-19
  • 2020-01-30
  • 2011-07-21
相关资源
最近更新 更多