完美的转发构造函数和继承构造函数
Perfect forwarding constructor and inheriting constructors
鉴于此 class 层次结构:
#include <iostream>
class Base {
public:
Base() = default;
Base(const Base&) { std::cout << " copy\n"; }
template<typename T>
Base(T&&) { std::cout << " T&&\n"; }
};
class Sub : public Base {
public:
using Base::Base;
};
is known 此代码将打印 T&&
:
// objects
Base varObj;
const Base constObj;
// invoking constructors
Base copy(varObj); // T&&
Base move(std::move(constObj)); // T&&
Base number(42); // T&&
为什么使用 Sub
而不是 Base
“解决”了这个问题?
// objects
Sub varObj;
const Sub constObj;
// invoking constructors
Sub copy(varObj); // copy
Sub move(std::move(constObj)); // copy
Sub number(42); // T&&
这是CWG2356:继承的构造函数仍然更适合非常量输入(因为需要限定转换),但它被丢弃了通过 [over.match.funcs]/8。这样做的部分原因是为了避免使任何继承构造函数的 class 可从其基础 class.
隐式转换
Sub
复制构造函数(您的两个初始化都使用)仍有可能调用构造函数模板。但是,它的源参数是 const Sub&
,所以它的基础子对象是 const Base&
。这是 与 Base
复制构造函数的 精确 匹配,因此它是在模板上选择的(否则由于限定转换或引用种类而获胜)。
鉴于此 class 层次结构:
#include <iostream>
class Base {
public:
Base() = default;
Base(const Base&) { std::cout << " copy\n"; }
template<typename T>
Base(T&&) { std::cout << " T&&\n"; }
};
class Sub : public Base {
public:
using Base::Base;
};
is known 此代码将打印 T&&
:
// objects
Base varObj;
const Base constObj;
// invoking constructors
Base copy(varObj); // T&&
Base move(std::move(constObj)); // T&&
Base number(42); // T&&
为什么使用 Sub
而不是 Base
“解决”了这个问题?
// objects
Sub varObj;
const Sub constObj;
// invoking constructors
Sub copy(varObj); // copy
Sub move(std::move(constObj)); // copy
Sub number(42); // T&&
这是CWG2356:继承的构造函数仍然更适合非常量输入(因为需要限定转换),但它被丢弃了通过 [over.match.funcs]/8。这样做的部分原因是为了避免使任何继承构造函数的 class 可从其基础 class.
隐式转换Sub
复制构造函数(您的两个初始化都使用)仍有可能调用构造函数模板。但是,它的源参数是 const Sub&
,所以它的基础子对象是 const Base&
。这是 与 Base
复制构造函数的 精确 匹配,因此它是在模板上选择的(否则由于限定转换或引用种类而获胜)。