Reputation: 1356
Let's say, a class Base
with following resorces:
struct Base
{
int m_int;
bool m_flag;
float m_float;
Base() = delete; // just to see that it didn't call
Base(int a, bool b, float c): m_int(a), m_flag(b), m_float(c) {}
};
Then I have a SubClass
which has a vector of Base
class as the resource.
Base
class resources can be created much efficiently as it avoids the unnecessary call of default constructors(please correct
me, if I am wrong).SubClass
Then I came up with following code for my SubClass
.
struct SubClass
{
private:
std::vector<Base> vec;
public:
SubClass() = delete; // just to see that it didn't call
// Idea - 1
//SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}
// Idea - 2
SubClass(std::initializer_list<Base> all): vec(all) {}
// Idea - 3 : but no more list initialization possible
template<typename ...Arg>
void addToClass(Arg&& ...args)
{
vec.emplace_back(std::forward<Arg>(args)...);
}
};
Then in the main()
, I can have following two possibilities to update resources in SubClass
:
int main()
{
// possibility - 1
SubClass obj
{
{1, true, 2.0f },
{5, false, 7.0f},
{7, false, 9.0f},
{8, true, 0.0f},
};
//possibility - 2: without list initialization
/*obj.addToClass(1, true, 2.0f);
obj.addToClass(5, false, 7.0f);
obj.addToClass(7, false, 9.0f);
obj.addToClass(8, true, 0.0f);*/
return 0;
}
Question - 1:
Which one of following is efficient or good to use(good practice) in above case? Why?
// Idea - 1
SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}
// Idea - 2
SubClass(std::initializer_list<Base> all): vec(all) {}
Question - 2:
Does addToClass(Arg&& ...args)
function works similar to any of the above two ideas?
Upvotes: 0
Views: 609
Reputation: 180825
First things first.
SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}
and
SubClass(std::initializer_list<Base> all): vec(all) {}
Don't do the same thing. The first also needs
SubClass(std::initializer_list<Base>& all): vec(all) {}
So you can initialize it with an lvalue std::initializer_list
(may never happen but it could). Passing by value covers both of those overloads so it is easier to write and it's performance is just about as good (it would take a lot of operations to really make a difference)
You can't move objects out of a std::initializer_list
since the objects as marked as const
so
SubClass(std::initializer_list<Base>&& all): vec(std::move(all)) {}
doesn't actually move anything.
As for addToClass
you can have both. You can have your template version that emaplces a single object into the class. You can also add an overload to take a std::initializer_list
so you can add multiple objects like
void addToClass(std::initializer_list<Base> all)
{
vec.insert(vec.end(), all.begin(), all.end());
}
and that will add all of the objects in all
to the end of vec
.
Upvotes: 1