I just wonder whether the following class will work properly. What I'm a bit scared of is the fact that in the constructor, on the marked line, I bind to values which are just (temporary) arguments. So the question is: Does std::bind take the arguments by-value? To me, this is not clear in the documentations I read.
class BoundFct {
public:
BoundFct(function<void(int, int)> fct, int v){
boundFct = bind(fct, v, _1); // ** PROBLEM HERE ? **
}
void call(int i){
boundFct(i);
}
private:
function<void(int)> boundFct;
};
As far as I tested, it works as intended. But is it a safe approach that will work properly in any case?
From std::bind:
The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref.
There's nothing unsafe about your code. Though it'd be better to take any function in your BoundFct constructor, rather than a std::function<>.
Related
Before I begin, I didn't find anything that completely explains my question in an other stackoverflow post so I decided to create my own. Apologies if it is already answered somewhere else(kindly point me to the existing post if it does exist).
Lets say we have the following two methods inside of a class:
int do_stuff(Thing& thing){ /* Do stuff... */} // L-value version
int do_stuff(Thing&& thing){ /* Do stuff... */} // R-value version
From what I have read, modern C++ has pretty much abandoned this kind of logic and it is recommending to just pass the Thing by value and let the compiler do it's magic. My question is, If I want to have two separate methods that explicitly handles L-values/R-values and avoid code duplication, which of the following is best(performance wise and as in best practice)?
int do_stuff(Thing& thing){ return do_stuff(std::move(thing)); } // The L-value version uses the R-value one
Or
int do_stuff(Thing&& thing){ return do_stuff(thing); } // The R-value version uses the L-value one since text is an L-value inside the scope of do_stuff(Thing&&)
Edit: The purpose of the question is for me to understand this simple case of move semantics and not to create a valid C++ API.
Edit #2: The print and std::string parts of the question are used as an example. They can be anything.
Edit #3: Renamed the example code. The methods do modify the Thing object.
If print doesn't change anything and only prints the string, it's best to take a const std::string & as const std::string & is able to bind to both lvalues and rvalues.
int print(const std::string& text) {}
Passing an argument by value does not mean it can't be an rvalue reference. The && just means that the parameter has to be an rvalue reference. Not having && doesn't mean the parameter can't be an rvalue reference.
When the argument is only used by the function, and with that, I mean if it's not modified, the best way to declare your function is:
int do_stuff(const Thing& thing);
That way, it is very clear to the reader that thing won't be modified. For most of the other cases, you should simply declare your function as:
int do_stuff(Thing thing);
passing the parameter by value, and not by reference or rvalue reference.
It used to be common to write code like this:
int do_stuff(Thing& thing)
{
/* change thing so that the caller can use the changed thing */
return success; // where success is an int
}
However, nowadays, it is often preferred to return the modified thing:
Thing do_stuff(Thing thing) { /* return modified thing */ }
In the example above:
int do_stuff(Thing thing);
the caller decides whether or not thing should be a copy:
do_stuff(my_thing); // copy - I need the original my_thing
do_stuff(std::move(thing)); // no copy - I don't need the original my_thing
Note that this declaration of do_stuff covers both of your versions:
int do_stuff(Thing&);
int do_stuff(Thing&&);
That said, you almost never need functions like:
int do_stuff(Thing&&);
unless for objects which cannot be copied like stream objects.
There is no difference in performance. std::move does nothing but casts the type of its argument, so a smart compiler will omit the call to std::move, and even omit the redundant call to do_stuff. You can see under -O2, in either case, GCC compiles the do_stuff that calls the other do_stuff to a simple jmp command to the other do_stuff.
So it is opinion-based which way is better. I personally like the second way because it is shorter.
I wrote a function which has this form:
Result f( const IParameter& p);
My intention is that this signature will make it clear that the function is not taking ownership of the parameter p.
Problem is that Result will keep a reference to IParameter:
class Result
{
const IParameter& m_p;
public:
Result( const IParameter& p )
: m_p( p ){ }
};
But then it happened that somebody called the function like this:
const auto r = f(ConcreteParameter{});
Unfortunately the temporary can be bound to const reference, and this caused a crash.
Question is: how can I make it clear that the function is not supposed to be called with temporaries, and maybe have a nice compilation error when that happens? Is it actually wrong in this case to state that it is not taking the ownership, since is passing it to result that will be propagated outside the function call scope?
The easiest way to make it clear is to overload the function with an rvalue reference parameter. Those are prefered to const references for temporaries so they will be chosen instead. If you then delete said overload, you'll get a nice compiler error. For your code that would look like:
Result f( const IParameter&& ) = delete;
You can also do the same thing with Result to gaurd it as well and that would look like:
class Result
{
const IParameter& m_p;
public:
Result( const IParameter& p )
: m_p( p ){ }
Result( const IParameter&& ) = delete;
};
In general, if a function receives value by const&, it's expected, that the function will use the value, but won't hold it. You do hold the reference to value so you should probably change argument type to use shared_ptr (if the resource is mandatory) or weak_ptr (if resource is optional). Otherwise you'll run into that kind of problems from time to time, as no one reads documentation.
It's hard to tell. The best way would be to document that Result must not live longer than the IParameter used to construct it.
There are valid cases of temporaries sent as constructor that is perfectly valid. Think about this:
doSomethingWithResult(Result{SomeParameterType{}});
Deleting the constructor taking temporaries would prevent such valid code.
Also, deleting the rvalue constructor won't prevent all cases. Think about this:
auto make_result() -> Result {
SomeParameterType param;
return Result{param};
}
Even if the constructor with temporary is deleted, invalid code is still really easy to make. You will have to document the lifetime requirement of your parameters anyways.
So if you have to document such behavior anyways, I would opt for what the standard library does with string views:
int main() {
auto sv = std::string_view{std::string{"ub"}};
std::cout << "This is " << sv;
}
It won't prevent constructing string views from temporary strings since it can be useful, just like my first example.
You can manually remove a constructor accepting an IParameter&& rvalue from the overload set:
class Result
{
// ...
public:
Result( IParameter&& ) = delete; // No temporaries!
Result( const IParameter& p );
};
When client code tries to instantiate an object via
Result f(ConcreteParameter{}); // Error
the constructor taking a const-qualified reference is no match because of the missing const-ness, but the rvalue constructor exactly matches. As this one is = deleted, the compiler refuses to accept such an object creation.
Note that as pointed out in the comments, this can be circumvented with const-qualified temporaries, see #NathanOliver's answer for how to make sure this doesn't happen.
Also note that not everyone agrees that this is good practice, have a look here (at 15:20) for example.
I already voted #NathanOliver answer as the best one, because I really think it is given the information I provided. On the other hand I would like to share what I think is a better solution to solve this very specific scenario when the function is more complex than the one in my initial example.
The problem with the delete solution is that it grows exponentially with the number of parameters, assuming that all the parameters needs to stay alive after the function call ends and you want a compile time check that the user of your API is not trying to give the ownership of those parameters to the function:
void f(const A& a, const B& b)
{
// function body here
}
void f(const A& a, B&& b) = delete;
void f(A&& a, const B& b) = delete;
void f(A&& a, B&& b) = delete;
We need to delete all the possible combination, and this will be hard to maintain on the long run. So my proposed solution is to take advantage of the fact that the reference_wrapper constructor which wraps T by move is already deleted in STD, and then write this:
using AConstRef = reference_wrapper<const A>;
using BConstRef = reference_wrapper<const B>;
void f(AConstRef a, BConstRef b)
{
// function body here
}
In this way all the invalid overload will be automatically deleted. I do not see any drawback with this approach so far.
Given the following working code (main.cpp):
#include <functional>
#include <iostream>
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback) // <--- this line
{
m_callback = std::bind(callback, std::placeholders::_1);
callback("hello world!\n");
}
};
// pretty boring class - a cut down of my actual class
struct helper
{
worker the_worker;
bool work_callback(std::string str)
{
std::cout << str << std::endl;
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });
}
Compiled with: -std=c++11 -O2 -Wall -Wextra -pedantic-errors -O2 main.cpp
I have comment the line in question (<-- this line - around line 7), where I think it would be more efficient to use: void do_work(std::function<bool(std::string)>&& callback) i.e. using the && move semantic.
I have never really used this, mostly because I still don't quite understand it.
My understanding is this:
void do_work(std::function<bool(std::string)> callback) - will take a copy of the lambda that I pass in (which is an rvalue I think).
void do_work(std::function<bool(std::string)> callback) - will move the lambda that I pass in because it is an rvalue.
My crude idea of an rvalue is any temporary variable.
Questions:
What I am not 100% clear about is, is what I wrote correct? and therefore is it safe to use &&. Both seem to work.
Does this && method also work if instead of passing a lambda like this:
the_helper.the_worker.do_work( [&](std::string data){ return the_helper.work_callback(data); });
we pass in std::bind(...):
the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1));
If the parameter is defined as an rvalue-reference, you must pass a temporary or cast an lvalue to an rvalue, like with std::move().
And the semantics of rvalue-references are that the caller should expect the passed argument to be plundered, rendering it valid but arbitrary, meaning mostly useless.
But the function receiving an rvalue-reference, despite having license to plunder, does not have any obligation to plunder. And if it doesn't explicitly do so, for example by passing that license on, then it doesn't come to pass, and nothing special happens.
Your code is such a case.
While I would ban std::bind from my vocabulary, using it or not doesn't actually make any significant difference.
In this case regardless of whether you pass by value or by rval ref a temporary std::function will have to be created, that's because a lambda is not really a std::function. In any case, you should move the std::function before assigning, to avoid making an unnecessary copy.
I'd recommend passing by value in this case, as this is a bit more flexible, and if you are passing lambdas, then it does not cause any harm, as the std::function will usually be constructed in place (so the temporary will not be moved into the function; this move can, and usually will, be elided).
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.
Sometimes we like to take a large parameter by reference, and also to make the reference const if possible to advertize that it is an input parameter. But by making the reference const, the compiler then allows itself to convert data if it's of the wrong type. This means it's not as efficient, but more worrying is the fact that I think I am referring to the original data; perhaps I will take it's address, not realizing that I am, in effect, taking the address of a temporary.
The call to bar in this code fails. This is desirable, because the reference is not of the correct type. The call to bar_const is also of the wrong type, but it silently compiles. This is undesirable for me.
#include<vector>
using namespace std;
int vi;
void foo(int &) { }
void bar(long &) { }
void bar_const(const long &) { }
int main() {
foo(vi);
// bar(vi); // compiler error, as expected/desired
bar_const(vi);
}
What's the safest way to pass a lightweight, read-only reference? I'm tempted to create a new reference-like template.
(Obviously, int and long are very small types. But I have been caught out with larger structures which can be converted to each other. I don't want this to silently happen when I'm taking a const reference. Sometimes, marking the constructors as explicit helps, but that is not ideal)
Update: I imagine a system like the following: Imagine having two functions X byVal(); and X& byRef(); and the following block of code:
X x;
const_lvalue_ref<X> a = x; // I want this to compile
const_lvalue_ref<X> b = byVal(); // I want this to fail at compile time
const_lvalue_ref<X> c = byRef(); // I want this to compile
That example is based on local variables, but I want it to also work with parameters. I want to get some sort of error message if I'm accidentally passing a ref-to-temporary or a ref-to-a-copy when I think I'll passing something lightweight such as a ref-to-lvalue. This is just a 'coding standard' thing - if I actually want to allow passing a ref to a temporary, then I'll use a straightforward const X&. (I'm finding this piece on Boost's FOREACH to be quite useful.)
Well, if your "large parameter" is a class, the first thing to do is ensure that you mark any single parameter constructors explicit (apart from the copy constructor):
class BigType
{
public:
explicit BigType(int);
};
This applies to constructors which have default parameters which could potentially be called with a single argument, also.
Then it won't be automatically converted to since there are no implicit constructors for the compiler to use to do the conversion. You probably don't have any global conversion operators which make that type, but if you do, then
If that doesn't work for you, you could use some template magic, like:
template <typename T>
void func(const T &); // causes an undefined reference at link time.
template <>
void func(const BigType &v)
{
// use v.
}
If you can use C++11 (or parts thereof), this is easy:
void f(BigObject const& bo){
// ...
}
void f(BigObject&&) = delete; // or just undefined
Live example on Ideone.
This will work, because binding to an rvalue ref is preferred over binding to a reference-to-const for a temporary object.
You can also exploit the fact that only a single user-defined conversion is allowed in an implicit conversion sequence:
struct BigObjWrapper{
BigObjWrapper(BigObject const& o)
: object(o) {}
BigObject const& object;
};
void f(BigObjWrapper wrap){
BigObject const& bo = wrap.object;
// ...
}
Live example on Ideone.
This is pretty simple to solve: stop taking values by reference. If you want to ensure that a parameter is addressable, then make it an address:
void bar_const(const long *) { }
That way, the user must pass a pointer. And you can't get a pointer to a temporary (unless the user is being terribly malicious).
That being said, I think your thinking on this matter is... wrongheaded. It comes down to this point.
perhaps I will take it's address, not realizing that I am, in effect, taking the address of a temporary.
Taking the address of a const& that happens to be a temporary is actually fine. The problem is that you cannot store it long-term. Nor can you transfer ownership of it. After all, you got a const reference.
And that's part of the problem. If you take a const&, your interface is saying, "I'm allowed to use this object, but I do not own it, nor can I give ownership to someone else." Since you do not own the object, you cannot store it long-term. This is what const& means.
Taking a const* instead can be problematic. Why? Because you don't know where that pointer came from. Who owns this pointer? const& has a number of syntactic safeguards to prevent you from doing bad things (so long as you don't take its address). const* has nothing; you can copy that pointer to your heart's content. Your interface says nothing about whether you are allowed to own the object or transfer ownership to others.
This ambiguity is why C++11 has smart pointers like unique_ptr and shared_ptr. These pointers can describe real memory ownership relations.
If your function takes a unique_ptr by value, then you now own that object. If it takes a shared_ptr, then you now share ownership of that object. There are syntactic guarantees in place that ensure ownership (again, unless you take unpleasant steps).
In the event of your not using C++11, you should use Boost smart pointers to achieve similar effects.
You can't, and even if you could, it probably wouldn't help much.
Consider:
void another(long const& l)
{
bar_const(l);
}
Even if you could somehow prevent the binding to a temporary as input to
bar_const, functions like another could be called with the reference
bound to a temporary, and you'd end up in the same situation.
If you can't accept a temporary, you'll need to use a reference to a
non-const, or a pointer:
void bar_const(long const* l);
requires an lvalue to initialize it. Of course, a function like
void another(long const& l)
{
bar_const(&l);
}
will still cause problems. But if you globally adopt the convention to
use a pointer if object lifetime must extend beyond the end of the call,
then hopefully the author of another will think about why he's taking
the address, and avoid it.
I think your example with int and long is a bit of a red herring as in canonical C++ you will never pass builtin types by const reference anyway: You pass them by value or by non-const reference.
So let's assume instead that you have a large user defined class. In this case, if it's creating temporaries for you then that means you created implicit conversions for that class. All you have to do is mark all converting constructors (those that can be called with a single parameter) as explicit and the compiler will prevent those temporaries from being created automatically. For example:
class Foo
{
explicit Foo(int bar) { }
};
(Answering my own question thanks to this great answer on another question I asked. Thanks #hvd.)
In short, marking a function parameter as volatile means that it cannot be bound to an rvalue. (Can anybody nail down a standard quote for that? Temporaries can be bound to const&, but not to const volatile & apparently. This is what I get on g++-4.6.1. (Extra: see this extended comment stream for some gory details that are way over my head :-) ))
void foo( const volatile Input & input, Output & output) {
}
foo(input, output); // compiles. good
foo(get_input_as_value(), output); // compile failure, as desired.
But, you don't actually want the parameters to be volatile. So I've written a small wrapper to const_cast the volatile away. So the signature of foo becomes this instead:
void foo( const_lvalue<Input> input, Output & output) {
}
where the wrapper is:
template<typename T>
struct const_lvalue {
const T * t;
const_lvalue(const volatile T & t_) : t(const_cast<const T*>(&t_)) {}
const T* operator-> () const { return t; }
};
This can be created from an lvalue only
Any downsides? It might mean that I accidentally misuse an object that is truly volatile, but then again I've never used volatile before in my life. So this is the right solution for me, I think.
I hope to get in the habit of doing this with all suitable parameters by default.
Demo on ideone