Inspired by my own StackOverflow question: [Should I always move on sink constructor or setter arguments?] (http://stackoverflow.com/questions/18673658/should-i-always-move-on-sink-constructor-or-setter-arguments)
Problem: passing sink arguments efficiently either requires performance trade-offs or extensive code duplication
struct Example {
std::string s1, s2;
Example(std::string mS1, std::string mS2) : s1{std::move(mS1)}, s2{std::move(mS2)} { }
};-
Passed argument is a temporary: it is moved without copies. Result: 1 move.
-
Passed argument is an lvalue: it is copied, then moved. Result: 1 copy + 1 move.
-
Pros: no code duplication.
-
Cons: unnecessary move when the passed argument is an lvalue.
struct Example {
std::string s1, s2;
Example(std::string&& mS1, std::string&& mS2) : s1{std::move(mS1)}, s2{std::move(mS2)} { }
Example(const std::string& mS1, std::string&& mS2) : s1{mS1}, s2{std::move(mS2)} { }
Example(std::string&& mS1, const std::string& mS2) : s1{std::move(mS1)}, s2{mS2} { }
Example(const std::string& mS1, const std::string& mS2) : s1{mS1}, s2{mS2} { }
};-
Passed argument is a temporary: it is moved without copies. Result: 1 move.
-
Passed argument is an lvalue: it is just copied. Result: 1 copy.
-
Cons: requires n^2 constructors/functions written by the developer!
Proposal: passing with std::sink<T> by value - behaves identically to Approach 2, avoids code duplication
struct Example {
std::string s1, s2;
Example(std::sink<std::string> mS1, std::sink<std::string> mS2) : s1{mS1}, s2{mS2} { }
};Thoughts?