I have a class whose constructor takes some vectors and stores them.
struct X {
X(std::vector<int> const& ints, std::vector<float> const& floats, std::vector<std::string> const& strings)
: ints_{ints}
, floats_{floats}
, strings_{strings}
{};
std::vector<int> ints_;
std::vector<float> floats_;
std::vector<std::string> strings_;
};
I would like to make the member variables into references, because in production code the values passed to the constructor are lvalues, whose lifetimes are longer than the object of class X.
However, unit tests usually construct X
es with temporaries, like this:
X x{ {42}, {3.14f}, {"hello"} };
If the members of X
are to be references, such calls should be prevented. This can be done by writing a constructor that takes rvalue references and making it =delete
.
X(std::vector<int> && ints, std::vector<float> && floats, std::vector<std::string> && strings) = delete;
This would prevent the instantiation if all arguments are temporaries. Unfortunately, it lets through calls where at least one argument is an lvalue:
std::vector<std::string> no_strings;
X x{ {42}, {3.14f}, no_strings };
because lvalue references are willing to bind to rvalues, so the (const&,const&,const&)
constructor can be called.
Do I have to write every combination of lvalue/rvalue ref arguments (all seven of them) and mark all of them as deleted?