C++ 模板右值 Ctor 与 Const 引用 Ctor

标签 c++ templates c++11 constructor

代码

#include <iostream>

using namespace std;

#define PF         cout << __PRETTY_FUNCTION__ << endl;

class berlp {
public:
    berlp() { }
    void p() { }
};

template <typename T>
class derp {
public:
    derp() = default;

    derp(const T & a) : mem(a) {
        a.p();
        mem.p();

        PF
    }

    template <typename U>
    derp(U && a) : mem(std::forward<U>(a)) {
        PF
    }

    T       mem;
};

int main(int argc, const char * argv[])
{
    berlp                   one;
    derp<berlp &>           f(one);     // problems with this list below
    derp<const berlp &>     h(one);     // problem with this follows

    return 0;
}

使用 XCode 和 CLang 输出 这一切都编译得很好,这是输出......

derp<berlp &>::derp(const T &) [T = berlp &]
derp<const berlp &>::derp(U &&) [T = const berlp &, U = berlp &]

问题

derp<berlp &> f(one); : derp 构造函数中的 a.p() 应该失败,因为“a”在引用折叠后是“const berlp &”,而 p() 不是 const。其次,用“a”(const berlp &)初始化“mem”(berlp &)应该不起作用。似乎“derp(const T & a)”中的“const”什么也没做。最后,为什么它甚至使用第一个构造函数而不是模板化的构造函数,它似乎可以在不破坏 const 的情况下完成所有这些?

derp<const berlp &> h(one); :为什么这个调用使用模板构造函数,而另一个似乎正是我们所追求的?这不是一个太可怕的问题,因为它似乎没有破坏任何东西,但它确实允许您修改构造函数中传递的 berlp,而另一个构造函数(应该)不应该。

所以,我要么非常困惑,要么出事了!请帮忙!

最佳答案

这里真的有很多问题:

  1. 为什么 derp<berlp&>(one)使用第一个构造函数?

    构造函数的声明是derp(T const&)变成 derp(berlp& const&)并折叠成 derp(berlp&)因为没有 const 这样的东西引用或引用引用。这在 8.3.2 [dcl.ref] 第 6 段中说明:

    If a typedef (7.1.3), a type template-parameter (14.3.1), or a decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type “lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.

    显然,传递一个 berlp&给构造函数使用 berlp&是完全匹配,模板构造函数不能做得更好。因此,选择了非模板构造器。

  2. 为什么调用 derp<berlp&>(one)berlp工作?

    这里没有真正的惊喜:mem类型为 berlp&并用 berlp& 初始化所以非 const成员都按预期工作。

  3. 使用 derp<berlp const&> 时并传递 berlp&模板构造函数是一个完美的匹配,显然是被选中的。 berlp const&类型的成员变量刚刚用 berlp& 初始化隐式转换为 berlp const& .这也不足为奇。

我认为您对引用折叠规则有点困惑。放置const放在错误的位置也无济于事:把它放在正确的位置实际上应该清楚大部分的困惑并且是 my preference 的一部分。把 const向右。

关于C++ 模板右值 Ctor 与 Const 引用 Ctor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19107851/

相关文章:

c++ - 如何在模板参数中分离函数类型返回类型和参数

string - ExtJS 如何从字符串动态创建小部件和布局

C++模板默认参数

c++ - 默认 lambda 作为函数的模板化参数

c++ - std::vector 的编译时间触发范围检查

c++ - 将字符串映射到类成员

c++ - 从 NSData 存储和恢复 std::vector

c++ - Thrust中是否有 boost 计算功能的类比?

C++/Boost 共享资源类,用于管理资源生命周期,如 shared_ptr

c++ - 如何使用基于范围的循环语法遍历 STL 容器中的连续对?