【问题标题】:C++ template specialization: unexpected function overload lookup resultC++ 模板特化:意外的函数重载查找结果
【发布时间】:2014-01-27 21:03:21
【问题描述】:

在尝试为 shared_ptr 编写一个包装器时,它会在支持继承类的同时隐藏用户的内存分配和释放,我偶然发现了非常奇怪的错误,表明编译器在重载期间查找错误的函数,或者我的知识关于混合重载和模板是错误的。所以我写了这个东西来测试:

#include <iostream>

void out(int i) {
    std::cout << i << '\n';
}

template <class T>
struct Inst {
    template <class TT>
    Inst(const TT &) {out(1);}
    Inst(const Inst &) {out(2);}
    template <class TT>
    Inst(TT &&) {out(3);}
    Inst(Inst &&) {out(4);}
    Inst() {out(-1);}
    ~Inst() {out(1000);}
};

class K {};
class KK : K {};

int main() {
    out(3000);
    K k; KK kk; Inst<K> i;
    Inst<K> I1{k};
    Inst<K> I2{kk};
    Inst<K> I3{i};
    Inst<K> I4{K()};
    Inst<K> I5{KK()};
    Inst<K> I6{Inst<K>()};
    out(2000);
}

我的合理预期是I1I2 写作1I3 写作2I4I5 写作3I6 写作@98765433以及至少两个其他对象在不同点写-1。但是,当使用 gcc 4.8.2 使用 -std=c++11 编译时,我的机器跳过了一个对象,并为每个其他调用的非自动构造函数编写了 3。我做错了什么?

【问题讨论】:

标签: c++ templates template-specialization specialization


【解决方案1】:

Inst(TT &amp;&amp;) {out(3);} 中的TT&amp;&amp; 有点特别。所以,特别的是,甚至为他们创造了一个特殊的“术语”,称为universal reference

简而言之,TT&amp;&amp; 不是您认为的那样。这里有两件事起作用:参考折叠模板推导

由于TT 是一个模板参数,并且您将&amp;&amp; 放在它前面,这就是您的示例中的T&amp;&amp;

Inst<K> I1{k};  ---> Inst(K&) 
Inst<K> I2{kk}; ---> Inst(KK&) 
Inst<K> I3{i};  ---> Inst(Inst<K>&) 
Inst<K> I4{K()};  ---> Inst(K&&) 
Inst<K> I5{KK()}  ---> Inst(KK&&)

发生的情况是TT&amp;&amp; 成为精确匹配,并且是您进行的所有调用的选定构造函数,这就是为什么您会看到每个调用的3iI6)。

更多阅读请看:

Universal References and the Copy Constructor.

Advantages of using forward.

【讨论】:

  • 嗯,确实如此。天哪,这是一个令人惊讶的语法。我想我就是不能让它做我认为它会做的事情?无论如何,谢谢你指点我这个词。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-25
相关资源
最近更新 更多