简体   繁体   中英

How to create + fill a container in-place?

I'm trying to create an array of classes that can't be copied or moved. So I need to create the objects in-place and I can't figure out how to do that:

#include <vector>

struct Foo {
  Foo(int) { }
  Foo(const Foo &) = delete;
  Foo & operator =(const Foo &) = delete;
  Foo(Foo &&) = delete;
  Foo & operator =(Foo &&) = delete;
};

struct Bla {
  Bla(const std::vector<int> & args) {
    for (auto i : args) {
      foo.emplace_back(i);
    }
  }
  std::vector<Foo> foo;
};

The compiler complains about the deleted move constructor because it's not guaranteed that all objects are constructed in-place and never moved. I don't have to use std::vector as container, so feel free to suggest something else.

You can use std::vector s iterator pair constructor to construct the objects like

Bla(const std::vector<int> & args) 
    : foo(args.begin(), args.end())
{}

If you have additional parameters that you need to include in the construction then you can switch to any of the node based containers like std::list

struct Bla {
  Bla(const std::vector<int> & args) {
    for (auto i : args) {
      foo.emplace_back(i, some_other_argument);
    }
  }
  std::list<Foo> foo;
};

One way is to use the range constructor. It doesn't reallocate the vector when random access iterators are passed:

Bla(const std::vector<int> & args) 
    : foo(args.begin(), args.end())
{}

For the most generic case isn't there some way to make an initializer list from the vector args and a lambda?

An alternative way to create a STL container of Foo that can't be copied or moved is containing std::unique_ptr<Foo> which is movable. For instance, as more generic case, if the first and second arguments of the ctor of Foo are int and double respectively, then the following Bla works for you:

DEMO

#include <tuple>
#include <vector>
#include <memory>

struct Bla
{
    Bla(const std::vector<std::tuple<int, double>>& args)
    {
        foo.reserve(args.size());

        for (const auto& i : args) {
            foo.push_back(
                std::make_unique<Foo>(std::get<0>(i), std::get<1>(i)));
        }
    }

    std::vector<std::unique_ptr<Foo>> foo;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM