我有一个带有非默认构造函数的类Object
和一个包含ManyObjects
数组的类Object
。用户应使用构造函数的参数来初始化此数组。
然后有一个类ManyObjectsWrapper
从ManyObjects
继承,并且还希望数组初始化ManyObjects
。
这是我当前正在使用的代码。
代码
#include <iostream>
#define PRINTFN() std::cout << __PRETTY_FUNCTION__ << std::endl
class Object {
public:
Object(int number) : number(number) { PRINTFN(); }
Object(Object &&o) : number(std::move(o.number)) { PRINTFN(); }
// Object(Object&&) = default;
void print() { std::cout << "The number is " << number << std::endl; }
private:
const int number;
};
template <size_t N>
class ManyObjects {
public:
ManyObjects(Object(&&objects)[N]) : objects(std::move(objects)) {}
void print() {
for (Object &object : objects)
object.print();
}
private:
Object objects[N];
};
template <size_t N>
class ManyObjectsWrapper : public ManyObjects<N> {
public:
ManyObjectsWrapper(Object(&&objects)[N])
: ManyObjects<N>(std::forward<Object[N]>(objects)) {}
};
int main() {
ManyObjectsWrapper<3> wrapper = {{1, 2, 3}};
wrapper.print();
}
输出
Object::Object(int)
Object::Object(int)
Object::Object(int)
Object::Object(Object&&)
Object::Object(Object&&)
Object::Object(Object&&)
The number is 1
The number is 2
The number is 3
它可以工作,并且输出看起来还不错,但是我不确定我使用右值引用和std::forward
和std::move
是否正确。
尤其是使用ManyObjects::objects
初始化objects(std::move(objects))
。
有人可以对此发表评论吗?
修改
一些澄清:我将其与不支持STL的微控制器平台一起使用。我可以通过手动移植来移植诸如std::forward
之类的简单编译时结构。但是,我不能使用std::vector
之类的动态容器,因为它们会使用堆,因此必须避免在使用的受限硬件上使用。
我想将依赖性降到最低,并且我不希望浪费时间移植大部分STL(例如std::array
)。
主要目标是能够调用ManyObjectsWrapper<3> wrapper = {{1, 2, 3}};
,其中参数将始终是整数文字的列表。
答案 0 :(得分:4)
完美转发仅对斯科特·迈耶斯(Scott Meyers)称为通用引用有意义。使用通用引用,我们不知道会得到右值还是左值,因此我们不能简单地std::move
参数,因为它可能只是左值引用。
在您的情况下,不存在通用引用。您的模板参数只是一个数字-数组大小。为了使右值引用成为通用引用,必须进行类型推断(通过模板或自动)-在您的示例中情况并非如此,因此您的引用只是简单的右值引用。
我已经非常简单地说明了这一点,有关通用引用的更多(更准确)信息,请参见this Scott Meyers article。