Herb Sutter\'s Back to the Basics! Essentials of Modern C++ presentation at CppCon discussed different options for passing parameters and compared their performance
I tried to fit these thoughts in a comment, but they would not fit. I presume to write this as I am mentioned both in the comments above, and in Herb's great talk.
Sorry to be late to the party. I have reviewed my notes and indeed I am guilty of recommending to Herb the original constraint for option 4 minus the errant !
. Nobody is perfect, as my wife will assuredly confirm, least of all me. :-)
Reminder: Herb's point (which I agree with) is start with the simple C++98/03 advice
set_name(const string& name);
and move from there only as needed. Option #4 is quite a bit of movement. If we are considering option #4, we are down to counting loads, stores and allocations in a critical part of the application. We need to assign name
to name_
just as fast as possible. If we are here, code readability is far less important than performance, though correctness is still king.
Providing no constraint at all (for option #4) I believe to be slightly incorrect. If some other code attempted to constrain itself with whether or not it could call employee::set_name
, it could get the wrong answer if set_name
is not constrained at all:
template
auto foo(employee& e, String&& name)
-> decltype(e.set_name(std::forward(name)), void()) {
e.set_name(std::forward(name));
// ...
If set_name
is unconstrained and String
deduces to some completely unrelated type X
, the above constraint on foo
improperly includes this instantiation of foo
in the overload set. And correctness is still king...
What if we want to assign a single character to name_
? Say A
. Should it be allowed? Should it be wicked fast?
e.set_name('A');
Well, why not?! std::string
has just such an assignment operator:
basic_string& operator=(value_type c);
But note that there is no corresponding constructor:
basic_string(value_type c); // This does not exist
Therefore is_convertible
is false
, but is_assignable
is true
.
It is not a logic error to try to set the name of a string
with a char
(unless you want to add documentation to employee
that says so). So even though the original C++98/03 implementation did not allow the syntax:
e.set_name('A');
It did allow the same logical operation in a less efficient manner:
e.set_name(std::string(1, 'A'));
And we are dealing with option #4 because we are desperate to optimize this thing to the greatest degree possible.
For these reasons I think is_assignable
is the best trait to constrain this function. And stylistically I find Barry's technique for spelling this constraint quite acceptable. Therefore this is where my vote goes.
Also note that employee
and std::string
here are just examples in Herb's talk. They are stand-ins for the types you deal with in your code. This advice is intended to generalize to the code that you have to deal with.