0

I have a class Foo with no sensible default constructor. I would also prefer to keep the copy-assignment operator private, although that may become impossible. (I'd like to make the class “almost” immutable, whence thread-safe, by having const fields and the small number of mutators that cast const way as private and early in the object lifetime.)

Creating std::vector<Foo> under these constraints is a little bit of a challenge. I came up with a solution I haven't seen elsewhere (see, for example, earlier SO question 1). I have a custom iterator which, when dereferenced, creates a Foo. It is set up such that each invocation increments to the next value of Foo in the vector. The sequence is easy to define. I define operator++, next, advance, distance and operator* on CustomIterator.

Then I have

std::vector<Foo> foo_vec{CustomIterator(0), CustomIterator(size_of_vector)};

No access issues. No unnecessary constructions. No copies. Anyone see a problem with this?

Andrew Lazarus
  • 18,205
  • 3
  • 35
  • 53
  • This looks cool, but why? Just create a static method in your class which will return vector of initialized objects. – Tarek Dakhran Mar 08 '20 at 21:38
  • How does the static method in the class create the vector to return? (That solves the operator= issues, and may be useful elsewhere.) – Andrew Lazarus Mar 08 '20 at 21:41
  • 1
    [Factory pattern](https://www.tutorialspoint.com/design_pattern/factory_pattern.htm) is your friend. – Eljay Mar 08 '20 at 21:41
  • Can't you just `emplace_back` the elements into the vector? That only requires a copy or move constructor, it does not require a copy or move assignment operator. – Brian Bi Mar 08 '20 at 21:50
  • @Brian Yes, I can have an empty vector and then initialize it with `emplace_back` in a loop. – Andrew Lazarus Mar 08 '20 at 21:52

1 Answers1

0

I will summarize the comments. The simple factory generates vector of initialized elements.

#include <vector>
class X {
    explicit X(int value) : value_(value) {}
    X& operator=(const X&) = default;
    friend std::vector<X> generate(int from, int to);
  public:
    const int value_;
};
// simplest factory ever
std::vector<X> generate(int from, int to) {
    std::vector<X> result;
    result.reserve(to - from);
    for (int k = from; k < to; ++k) {
        result.emplace_back(std::move(X(k)));
    }
    return std::vector<X>();
}
int main() {
    auto v = generate(0, 10);
    static_cast<void>(v);
}
Tarek Dakhran
  • 2,021
  • 11
  • 21