In a code review, my co-worker and I were discussing the interface for a function I was writing. Our code base uses C++17 and we do not use exceptions (video games).
I claimed that the idiomatic C++ way of taking sink parameters would be performant while also keeping the interface flexible, allowing the caller to pass a copy or move from an owned value as desired. By idiomatic way, I mean either one function taking the parameter by value, or an overoad set for const lvalue and rvalue references (which requires one less move in the lvalue case, at the cost of some code duplication).
struct A {};
class ByValue
{
public:
ByValue(std::vector<A> v)
: m_v(std::move(v))
{}
private:
std::vector<A> m_v;
};
class RefOverloads
{
public:
RefOverloads(std::vector<A> const& v)
: m_v(v)
{}
RefOverloads(std::vector<A>&& v)
: m_v(std::move(v))
{}
private:
std::vector<A> m_v;
};
int main()
{
std::vector<A> v0;
ByValue value0(v0);
ByValue value1(std::move(v0));
std::vector<A> v1;
RefOverloads ref0(v1);
RefOverloads ref1(std::move(v1));
}
My coworker on the other hand does not like that it is easy to implicitly make expensive copies. He would prefer that these sink arguments are always by rvalue reference (with no const lvalue ref overload), and that if the caller wishes to pass a copy they must make a local copy and move it into the function.
class RvalueRefOnly
{
public:
RvalueRefOnly(std::vector<A>&& v)
: m_v(std::move(v))
{}
private:
std::vector<A> m_v;
};
int main()
{
std::vector<A> v;
//RvalueRefOnly failedCopy(v); // Fails purposefully.
std::vector<A> vCopy = v; // Explicit copy of v.
RvalueRefOnly okCopy(std::move(vCopy)); // Move into okCopy.
}
I've never even thought of an interface like this. A counter-argument I had was that taking by value expresses intent better, i.e, with signature
void f(T x);
the caller knows that f
has taken ownership of x
. With
void g(T&& x);
g
may have ownership or may not, depending on the implementation of f
.
Is there a best way? Am I missing some argument one way or the other?
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…