Extending lifetime of temporary - proper way - c++

Say I have:
f(T& t){ ... }
which I sometimes want to provide argument for from a function call
T GetT() { ... }
like this:
f(GetT())
Which won't compile even though I'm convinced that the lifetime of T is guaranteed to last until the end of expression, I also cannot change the T& to const T& because I need to modify the object inside f.
I thought about using T&& but then when I happen to have lvalue of T I would need to move() it, which would make it awkward because I sometimes need to use T after the call to f. In my case T is plain old data so I guess it would work but it doesn't feel right to move an object and use it afterwards.
Is there an elegant way to allow function to take both rval and lval refs to mutable object?
ATM I'm just doing
T t = GetT();
f(t);
Which I feel is at least one useless line and one useless copy of T.

How about using universal references.
Not sure if you would consider it elegant but it would look something like this:
struct MyStruct
{
int i;
};
template<class T>
void foo(T&& t)
{
static_assert(std::is_base_of<MyStruct,
typename std::remove_reference<T>::type>::value, "ERROR");
t.i = 1024;
}
MyStruct GetMyStruct()
{
return MyStruct();
}
int main()
{
foo(GetMyStruct());
MyStruct ms;
foo(ms);
return 0;
}

The way that you're currently doing, i.e. storing the object in a variable, is a proper way to extend the lifetime of the returned object and allow non-const references to bind to it. If GetT is implemented so that (N)RVO is possible, then no useless copy need to be made because it can be elided.

I came up with a solution to my problem with simple overload:
f(T& t) { ... }
f(T&& t) { f(t); }
But there still has to be a better way.

You cannot bind a reference to a temporany: only const reference can do that.
I suggesto you to look this link C++11 binding rules for const &&

Related

Does an std::optional parameter create a copy?

I have a function that takes an std::optional
void foo(const std::optional<T>& opt);
But copying T is expencive.
Does this create a copy of T?
If so, how can I not create a copy?
As clarified by your follow up comment, you are calling the function foo like this:
T t;
...
foo({t});
In this case, the answer is yes. A copy of t will be created. To avoid that, you can use std::reference_wrapper to avoid copying:
void foo(const std::optional<std::reference_wrapper<const T>> &optT) {
...
}
With these changes to the function, calling the it in the same manner will not result in creation of a copy.
Yes, std::optional stores a copy of whatever you pass to it. The C++17 standard explicitly prohibits storing references in std::optional. See: https://en.cppreference.com/w/cpp/utility/optional#:~:text=There%20are%20no%20optional%20references
As suggested by others, passing std::optional<std::reference_wrapper<const T>> is one way to avoid making copies.
void foo(const std::optional<std::reference_wrapper<const T>>& opt) {
if (opt) {
// Do something.
}
}
T t;
foo(t);
But consider that the C++ committee had good reasons for disallowing references in std::optional. For instance, an "optional reference" essentially describes what a plain pointer does, and plain pointers don't suffer from the long type name.
void foo(const T* opt) {
if (opt) {
// Do something.
}
}
T t;
foo(&t);
I think you will find useful this documentation page. See the section about "Optional function parameters".
When you call the function and pass an instance of T, an optional will be constructed which will own its own copy of T, therefore it will call T's copy constructor.
int main()
{
T t;
optional<T> ot;
foo(t); // will create a copy
foo(ot); // won't create a copy
}
If you're using boost::optional, not std::optional, you can declare foo as receiving an optional reference, i.e.
void foo(boost::optional<const T&> t)

How do I safely hold on to a C++ const reference?

aka. how do I prevent a const& parameter from accidentally binding to a temporary?
We have a class that essentially looks like this:
template<typename T>
struct Observer {
const T* target;
void observe(const T& x) {
target = &x;
}
};
That is, these objects will "hold on" to the const-ref they get passed.
We had a bug where the observe function accidentally got passed a temporary object - something that can never be valid for this case.
What options do we have to prevent accidentally binding to a temporary?
Changing the signature to (const T* px) would work technically (taking the address of a temporary is a compiler warning=error here) it is not very attractive for other reasons.
Side note: Yeah, this will always have potential lifetime management issues, but so far the real thing worked pretty well because of its limited usage pattern - but passing temporaries accidentally has been observed in practice, so we want to possibly address that first.
You can add a rvalue reference overload, and delete it:
void observe(const T&& x) = delete;
Now a compile error will be issued if someone tries to pass a temporary.

Spamming std::move is the way to go?

About std::move, here is what I can interpret, according to http://en.cppreference.com/w/cpp/utility/move :-
If I want to transfer ownership, I have to call std::move (or in rare case, std::forward).
Responsibility of std::move is calling operator=(A&& other).
The most essential step of the move operation is supposed to be implemented in operator=(A&&).
It is tricky to ensure that operator=(A&&) would be called. It need a special converter.
There are only two converters in the C++ world that can convert variables into xvalue (the &&) : std::move and std::forward.
Question
After adding many of std::move(std::unique_ptr) in my code, I start to worry that for such basic feature like transfer ownership, I have to heavily rely on the standard library (std::).
Do I really have to use std::move to transfer ownership?
Is spamming and hard-code calling std::move in many places of code-base a correct way to go for a high-standard program?
Should std::move be encapsulated?
They are actually a single question, but ask in different perspectives.
Edit
As request, here is my trial & error. It compiled ok.
I have no problem about the code, but I worry about its approach / pattern.
https://ideone.com/y8Pcgf
class T{
public: int value;
public: T(int a=1234){
value = a;
}
};
int main() {
std::unique_ptr<T> t1 = std::unique_ptr<T>(new T(1));
void* databaseNew=operator new [](sizeof(std::unique_ptr<T>));
std::unique_ptr<T>* t1ptr=static_cast<std::unique_ptr<T>*>(databaseNew);
new (t1ptr) std::unique_ptr<T>(std::move(t1));
return 0;
}
Rule of thumb:
If you're in a deduced x-value context, use std::forward:
template<class T>
void foo(T&& t) // T is deduced x-value, so we forward it
{
bar(std::forward<T>(t));
}
Otherwise use std::move
template<class T>
void foo1(std::vector<T> v) // although vector<T> is deduced, it's not an x-value
{
bar(std::move(v)); // so move it
}
template<class T>
void foo2(std::vector<T>&& v) // although vector<T> is deduced, it's not an x-value.
// In this case an r-value reference
{
bar(std::move(v)); // so move it
}
template<class T>
void foo3(std::vector<T>& v) // although vector<T> is deduced, it's not an x-value.
// In this case an l-value reference
{
bar(std::move(v)); // so move it
}
void foo4(std::vector<int> v) // complete type
{
bar(std::move(v)); // so move it
}
void foo5(std::vector<int> const & v) // const reference
{
bar(v); // not much point in moving it. std::move would cast it
// to std::vector<int> const&&, which although is detectable
// decays to std::vector<int> const&
}
which although is detectable... what?
It is permissible, if not necessarily advisable to write code like this:
#include <iostream>
struct X
{
void foo() const &
{
// do one thing...
std::cout << "one thing\n";
}
void foo() const &&
{
// do something else...
std::cout << "or another\n";
}
};
int main()
{
const X x;
x.foo();
std::move(x).foo();
}
const r-value references do exist, it's just that no-one uses them because there is no reasonable use-case.
The need to explicitly move, of which you complain, was actually done on purpose. Before unique_ptr, STL had a horrid construct called auto_ptr. It would move ownership impllicitly, and was borderline unusable unless you really really really knew what you were doing.
To make things more usable, in most cases C++ now requires you to explicitly state that you intend on moving ownership over a container, by using std::move.
In fact, std::move is little more than a cast to an rvalue reference.
There are cases where such an explicit specification is not necessary. For example, if the container from which you take ownership is already an rvalue (e.g. - a temporary object), then no case using std::move is necessary. For example, the following doesn't compile:
std::unique_ptr<int> a;
a = new int;
But the following does, without needing a move:
std::unique_ptr<int> a;
a = std::unique_ptr<int>(new int);
The reason this does not need a call to std::move, despite invoking the move operator, is that the object we move the ownership away from is already a temporary object (i.e. - an rvalue), so no cast is necessary.
Another example is if you call a function that returns a unique_ptr. You might have to call std::move inside the function to get it into the return value, but you do not need to call std::move on the function's return value to get it into the outside unique_ptr. It is already an rvalue, and therefor no cast is necessary.

Is there a way to make passing by reference, and passing by value explicit in the function call?

If you were to look at this code,
int x = 0;
function(x);
std::cout << x << '\n';
you would not be able to verify through any means of syntax, that parameter x is being passed by reference or that it's being passed by value. The only way you would know for sure, is if you looked at either the function declaration or function definition.
Here is a simple example of how I believe this could be a problem:
std::string Lowercase(std::string str); //<- this is hidden away in code; probably in a different file.
int main(){
std::string str = "HELLO";
Lowercase(str);
std::cout << str << '\n'; //<- Bug! we expected to output "hello". The problem is not very easy to spot, especially when a function name sounds as though it will change the passed in value.
}
In order to avoid having to jump between the function call and the function declaration (or in some cases, the documentation) in order to understand the function behavior, is there a way to explicitly document in the syntax of a function call that the parameter is expected to change (i.e. a reference parameter) or that a copy is being sent (i.e. pass by value)?
I realize that there is also the option of passing by const& which has the similar notion to passing by value, in that the variable passed in, will not have its value changed after the function call.
I'm sure there are all kinds of situations in the language that might add to the complexity of understanding how a parameter is being passed-
but I'm curious, is there a way to combat this problem in the way I want to?
I've noticed that some people write two similar functions. One of them takes a value parameter, the other one takes a pointer. That allows calling a function like this:
Lowercase(str); //we assume the value will not change
Lowercase(&str); //we assume the value will change
But this solution has many other issues, and I would not like to lose the benefit of references. Plus, we are still making assumptions on the behavior.
Some people insist that the correct way to pass mutable object is to use a pointer. That is, you would pass
Lowercase(&str);
... and Lowercase() would, obviously, be implemented to take a pointer. That approach may suit your needs.
I want to mention, however, that this is not what I would do! Instead, the approach I favor is to use appropriate names instead. For example,
inplace_lowercase(str);
pretty much says what it is going to do. Clearly, inplace_lowercase() would actually be an algorithm and with a bit of magic could be reasonably be called as
inplace_lowercase(str.begin() + 1, str.end());
as well.
Here are a few reasons why I don't like passing arguments by pointer and/or why I don't believe in an explicit indication of how the argument is passed:
Pointers can be null. A mandated reference parameters should, in my opinion, be a reference.
Passing by pointer still doesn't indicate whether the argument may be modified are not as the argument may be a T const*.
Having meaningful names makes it actually easier to understand what's going on in the first place.
Calling something without consulting its documentation and/or knowing what the called function will do doesn't work anyway and indicating how things are passed is trying to cure symptoms of a deeper problem.
I'm not sure I understand your requirements completely, but maybe this is something you can use:
template<typename T>
void foo( T ) { static_assert( sizeof(T)==0, "foo() requires a std::ref" ); }
void foo( std::reference_wrapper<int> t )
{
// modify i here via t.get() or other means of std::reference_wrapper
}
int main()
{
int i = 42;
// foo( i ); // does not compile, static_assert fires
foo( std::ref( i ) ); // explicit std::ref visible on the caller's side
}
Many (most) IDE's help you with this problem by displaying the function/method prototype(s) once they figure out which function you are calling.
This is C++: the lack of in and out parameters doesn't mean the language is deficient, it means you need to implement what other languages would do as a language feature as a library.
Create two template classes and functions.
in_param<T> is a wrapper around a T const&, whilie io_param<T> is a wrapper around a T& reference. You construct them by calling helper functions in and io.
Inside, they behave like references (via overloading).
Outside, the caller must call in or io on the argument, marking it up at the call site.
out is trickier: inside the fumction, only assignment is legal. Ideally we would not even construct it: an emplace method might help.
However, the caller needs some channel to know if the parameter was constructed or not.
What I would do is out_param only has operator=, and it assigns. out wraps something into an out_param. If you want delayed constructuon, use optional inside the out param, which gets close. Maybe out_param also has emplace, which usually just assigns, but if the tyoe wrapped has emplace calls it instead?
template<typename T>
struct in_param : std::reference_wrapper<T const> {
explicit in_param( T const& t ):std::reference_wrapper<T const>(t) {}
in_param( in_param<T>&& o ):std::reference_wrapper<T const>(std::move(o)) {}
void operator=( in_param<T> const& o ) = delete;
};
template<typename T>
struct io_param : std::reference_wrapper<T> {
explicit io_param( T& t ):std::reference_wrapper<T>(t) {}
io_param( io_param<T>&& o ):std::reference_wrapper<T>(std::move(o)) {}
};
template<typename T>
in_param< T > in( T const& t ) { return in_param<T>(t); }
template<typename T>
io_param< T > io( T& t ) { return io_param<T>(t); }
template<typename T>
struct out_param {
private:
T& t;
public:
out_param( T& t_ ):t(t_) {}
out_param( out_param<T>&& o ):t(o.t) {}
void operator=( out_param<T> const& o ) = delete;
void operator=( out_param<T> && o ) = delete;
void operator=( out_param<T> & o ) = delete;
void operator=( out_param<T> && o ) = delete;
template<typename U>
out_param<T>& operator=( U&& u ) {
t = std::forward<U>(u);
return *this;
}
// to improve, test if `t` has an `emplace` method. If it does not,
// instead do t = T( std::forward<Us>(us)... ). (I'd use tag dispatching
// to call one of two methods)
template<typename... Us>
void emplace( Us&&... us ) {
t.emplace( std::forward<Us>(us)... );
}
};
template<typename T>
out_param<T> out( T& t ) { return out_param<T>(t); }
or something like the above.
You now get syntax like:
void do_stuff( int x, in_param<expensive> y, io_param<something> z, out_param<double> d );
int main() {
expensive a;
something b;
double d;
do_stuff( 7, in(a), io(b), out(d) );
}
and failure to call in, io or out at the call site results in compile time errors. Plus, out_param makes it quite difficult to accidentally read the state of the out variable within the function, producing some very nice documentation at the call site.
If you use MS VC++ then maybe it will be useful information about source-code annotation language (SAL)
http://msdn.microsoft.com/ru-ru/library/hh916383.aspx
I think it's something useless to notify (by language nonetheless [1]). The only needed question is : "Is my object is semantically modified ?", and so :
When you read a prototype you know if a function could modify an object (non-const ref) or not (copy or const ref).
When you use a function (even without reading [2] the prototype) if you have to be sure to not modify an object, use a const_cast.
[1] A static analyzer could do it for its purposes.
[2] If you miss, the compiler would warn you anyway.
That is the whole point of pass-by-reference -- that syntactically don't need to do anything different from passing by value.

Is pass-by-value a reasonable default in C++11?

In traditional C++, passing by value into functions and methods is slow for large objects, and is generally frowned upon. Instead, C++ programmers tend to pass references around, which is faster, but which introduces all sorts of complicated questions around ownership and especially around memory management (in the event that the object is heap-allocated)
Now, in C++11, we have Rvalue references and move constructors, which mean that it's possible to implement a large object (like an std::vector) that's cheap to pass by value into and out of a function.
So, does this mean that the default should be to pass by value for instances of types such as std::vector and std::string? What about for custom objects? What's the new best practice?
It's a reasonable default if you need to make a copy inside the body. This is what Dave Abrahams is advocating:
Guideline: Don’t copy your function arguments. Instead, pass them by value and let the compiler do the copying.
In code this means don't do this:
void foo(T const& t)
{
auto copy = t;
// ...
}
but do this:
void foo(T t)
{
// ...
}
which has the advantage that the caller can use foo like so:
T lval;
foo(lval); // copy from lvalue
foo(T {}); // (potential) move from prvalue
foo(std::move(lval)); // (potential) move from xvalue
and only minimal work is done. You'd need two overloads to do the same with references, void foo(T const&); and void foo(T&&);.
With that in mind, I now wrote my valued constructors as such:
class T {
U u;
V v;
public:
T(U u, V v)
: u(std::move(u))
, v(std::move(v))
{}
};
Otherwise, passing by reference to const still is reasonable.
In almost all cases, your semantics should be either:
bar(foo f); // want to obtain a copy of f
bar(const foo& f); // want to read f
bar(foo& f); // want to modify f
All other signatures should be used only sparingly, and with good justification. The compiler will now pretty much always work these out in the most efficient way. You can just get on with writing your code!
Pass parameters by value if inside the function body you need a copy of the object or only need to move the object. Pass by const& if you only need non-mutating access to the object.
Object copy example:
void copy_antipattern(T const& t) { // (Don't do this.)
auto copy = t;
t.some_mutating_function();
}
void copy_pattern(T t) { // (Do this instead.)
t.some_mutating_function();
}
Object move example:
std::vector<T> v;
void move_antipattern(T const& t) {
v.push_back(t);
}
void move_pattern(T t) {
v.push_back(std::move(t));
}
Non-mutating access example:
void read_pattern(T const& t) {
t.some_const_function();
}
For rationale, see these blog posts by Dave Abrahams and Xiang Fan.
The signature of a function should reflect it's intended use. Readability is important, also for the optimizer.
This is the best precondition for an optimizer to create fastest code - in theory at least and if not in reality then in a few years reality.
Performance considerations are very often overrated in the context of parameter passing. Perfect forwarding is an example. Functions like emplace_back are mostly very short and inlined anyway.