c++ - 构造函数中的完美转发 (C++17)

标签 c++ gcc language-lawyer c++17 template-argument-deduction

考虑下面的代码

struct A {
    A(int id) : id_ { id } {}

    A(const A& rhs) { std::cout << "cctor from " +
        std::to_string(rhs.id_) << std::endl; }
    A(A&& rhs) { std::cout << "mctor from " +
        std::to_string(rhs.id_) << std::endl; }

    int id_;
};

template<typename T>
struct B1 {
    constexpr B1(T&& x) noexcept : x_ { std::forward<T>(x) } {}

    T x_;
};

template<typename T>
struct B2 {
    constexpr B2(T&& x) noexcept;

    T x_;
};

template<typename T>
constexpr
B2<T>::B2(
    T&& x
) noexcept :
    x_ { std::forward<T>(x) } {
}

int
main(
) {
    A a { 1 };

    //B1 b11 { a }; // Not compiling
    B1 b12 { A { 2 } };

    B2 b21 { a };
    B2 b22 { A { 3 } };

    return 0;
 }

产生

mctor from 2
mctor from 3

所以它基本上看起来好像外部定义的构造函数完美地转发了其参数的值类别,而内联定义的构造函数却没有。

外部定义的构造函数是像函数模板一样处理(完美地转发其参数)还是这里发生了什么?

欢迎提供标准相应部分的链接。

我使用的是 GCC 7.2.0。

最佳答案

这是一个 GCC 错误。转发引用有一个非常明确的定义:

[temp.deduct.call] (emphasis mine)

3 A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.

在这两种情况下,T 在 CTAD 期间命名封闭类的模板参数,因此它不应该产生任何一种转发引用。内联或在类定义之外定义的 c'tor 与此无关。

关于c++ - 构造函数中的完美转发 (C++17),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53519699/

相关文章:

c - 用C语言从M68k ram地址中获取特定的十六进制

c++ - 如何映射项目坐标?

c++ - 如何使用 Boost 预处理器多次打印逗号

c++ - 与 shell 脚本不同,批处理文件不可执行吗?

c++ - 如何在静态库中的单独 cpp 文件中链接未引用的变量?

c++ - 我如何使用 §8.3.1 和 §8.3.4 推断像 '[]' 这样的后缀声明符运算符比像 '*' 这样的前缀运算符绑定(bind)得更紧密?

c++ - 当 C++ 中的数组大小未知时,如何在运行时将对字符串数组的引用作为函数参数传递?

gcc - 为什么 GCC (ARM Cortex-M0) 在应该知道数据已经是 uint8 的情况下生成 UXTB 指令

c - 表达式的右手边总是先求值

c++ - 构造函数初始化列表中的 'this'指针