-1

I was on my way to create a class that would mimic std::vector to a certain extend.

I quickly faced a problem where I couldn't create an array of objects which didn't have a default constructor. I found the answer here https://stackoverflow.com/a/4756306/8106847 which allowed me to do just that. But the problem now is I'm stuck to one certain constructor.

How do I pass any constructor like std::vector<Obj>(100, Obj(1, "str")) does ?

(or is it far too complicated for anyone who's not senior C++ developer?)

1 Answers1

1

I'm not sure what you exactly want but if you want to initialize the list with some default values and then use a different way to construct others, you can manipulate the list however you want. Let me elaborate more:

Suppose this is how you've defined your Obj (in the future, it'd be helpful to include your implementation of Obj)

class Obj {
public:
  explicit Obj(int arg1, std::string arg2) : arg1_(arg1), arg2_(std::move(arg2)) {}
  explicit Obj(std::string arg2) : arg1_(25), arg2_(std::move(arg2)) {}

private:
  int arg1_;
  std::string arg2_;
};

Now vectors can take a capacity and an optional default value. If your type doesn't have a constructor that takes no values, you can't create the vector like this (without specifying the default value so you have to pass the default value by creating one instance of that object using whatever constructor you want). You can always create an empty vector and then add items to it one by one. To enhance performance, if you know how many items you're going to have, you can reserve memory spots for them but don't add them just yet. This way, you don't have to worry about constructor because no objects will be created just yet. The last code snipped in this post demonstrates how to do this. If you have an int, you can do this:

std::vector<int> myInts{50, 1};  // make a vector of 50 items with default value of 1
myInts[1] = 26;  // change the second value to be 26.

You can do the same thing with Obj

Obj defaultValue{100, "Type1"};
std::vector<Obj> myObjs{50, defaultValue};  // make a vector of 50 Objs with copies of defaultValue.

Note that these are copies so if you change one of them, it won't change the other ones. The following is the same as above but it's in one line (passing rvalue instead of lvalue).

std::vector<Obj> myObjs{50, Obj{100, "Type1"}};  // same thing as above.

Now if you want some items to be constructed differently, you can assign different values.

std::vector<Obj> myObjs{50, Obj{100, "Type1"}};
myObjs[0] = Obj{"Type2"};

If you have a lot of different ways of initializing this. Then what you can do is to avoid creating the list with a default value and add items to the vector one by one.

std::vector<Obj> myObjs;
myObjs.reserve(100);  // expand the capacity but don't actually create any items.
myObjs.push_back(Obj{10, "Type1"});
myObjs.push_back(Obj{"Type2"});
Peyman
  • 3,059
  • 1
  • 33
  • 68