At C++Now 2018, I wrote three blog posts during the conference. This year I was somehow so busy at C++Now that I merely wrote a list of things I ought to blog about once I got the time. So here’s the first one.

On Wednesday afternoon, Vittorio Romeo gave a very good summary of his proposed function_ref . It’s a very well-defined type; because it is non-owning and trivially copyable, it can sidestep the majority of design decisions that are the bugbear of std::function ’s awkward design. (See “The space of design choices for std::function ,” 2019-03-27.)

However, during the talk, David Sankel made an interesting observation. Consider:

template<class T> T one(std::reference_wrapper<T> arg) { T local = arg; return local; } int main() { std::string s = one("hello"s); std::cout << s << "

"; }

arg is a reference to a temporary, but by converting it to T local , we get a copy by value.

Or consider:

std::string two(std::string_view arg) { std::string local(arg); return local; } int main() { std::string s = two("hello"s); std::cout << s << "

"; }

arg is a view to a temporary, but by converting it to std::string local , we get a copy by value. (Notice that this conversion is marked explicit , so std::string local = arg; won’t compile — thanks to Jason Cobb for the correction!)

But consider:

std::function<int()> three(std::function_ref<int()> arg) { std::function<int()> local = arg; return local; } int main() { std::function<int()> f = three([x=42](){ return x; }); std::cout << f() << "

"; }

arg is a view to a temporary. By converting it to std::function<int()> local , we get a copy of the view — the resulting std::function has reference semantics, and when we call it on the last line of main , we dereference a dangling reference and produce undefined behavior.

This interaction is cute, but I definitely don’t want to imply that function_ref (or function ) should be derailed over it. The conclusion falls out fairly intuitively from the fact that string_view is a view over data, whereas function_view is a view over code.

Data can be serialized; therefore it can be copied, and also compared for equality (remember, “copies compare equal”). Therefore the conversion from string_view to string has value semantics, and both string and string_view provide an operator== .

Code cannot be serialized; therefore it cannot be copied, nor can it be compared for equality. Therefore the conversion from function_ref to function (or from reference_wrapper to function ) has reference semantics, and neither function nor function_ref provide an operator== .