完美的对象转发阵列

时间:2018-07-19 09:38:47

标签: c++ move-semantics

我有一个带有非默认构造函数的类Object和一个包含ManyObjects数组的类Object。用户应使用构造函数的参数来初始化此数组。

然后有一个类ManyObjectsWrapperManyObjects继承,并且还希望数组初始化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::forwardstd::move是否正确。 尤其是使用ManyObjects::objects初始化objects(std::move(objects))
有人可以对此发表评论吗?

修改

一些澄清:我将其与不支持STL的微控制器平台一起使用。我可以通过手动移植来移植诸如std::forward之类的简单编译时结构。但是,我不能使用std::vector之类的动态容器,因为它们会使用堆,因此必须避免在使用的受限硬件上使用。
我想将依赖性降到最低,并且我不希望浪费时间移植大部分STL(例如std::array)。

主要目标是能够调用ManyObjectsWrapper<3> wrapper = {{1, 2, 3}};,其中参数将始终是整数文字的列表。

1 个答案:

答案 0 :(得分:4)

完美转发仅对斯科特·迈耶斯(Scott Meyers)称为通用引用有意义。使用通用引用,我们不知道会得到右值还是左值,因此我们不能简单地std::move参数,因为它可能只是左值引用。

在您的情况下,不存在通用引用。您的模板参数只是一个数字-数组大小。为了使右值引用成为通用引用,必须进行类型推断(通过模板或自动)-在您的示例中情况并非如此,因此您的引用只是简单的右值引用。

我已经非常简单地说明了这一点,有关通用引用的更多(更准确)信息,请参见this Scott Meyers article