Passing reference_wrapper objects as function arguments in C++11 - c++

How does one pass and operate on constant (or non constant) references inside STL containers. Say I have a function:
bool foo(const Obj& A, const Obj& B) {
// do some computation on A & B
}
and since A & B always occur together, I would like to put them in an STL pair:
bool foo(const std::pair<Obj, Obj>& A_and_B) {
// do some computation on A & B
}
However now both objects A & B get copied into a pair every time foo needs to be called. Looking around I found reference_wrapper in C++11. Though doing something like this doesn't quite work:
bool foo(const std::pair<std::reference_wrapper<Obj>, std::reference_wrapper<Obj>>& A_and_B) {
// do some computation on A & B
}
bool foo(const std::pair<Obj, Obj>& A_and_B) {
foo(std::make_pair(std::ref(A_and_B.first), std::ref(A_and_B.second)));
}
What is the correct way of passing containers with reference values without using pointers?

To avoid copy when make_pair, why not define the pair as std::pair<Obj&, Obj&> directly?
#include <iostream>
#include <string>
#include <functional>
class Obj
{
};
bool foo(const std::pair<Obj, Obj>& A_and_B) {
// do some computation on A & B
std::cout << __func__ << std::endl;
}
bool foo(const std::pair<Obj&, Obj&>& A_and_B) {
// do some computation on A & B
std::cout << "ref version foo" << std::endl;
}
int main( void )
{
Obj A;
Obj B;
foo( std::make_pair(std::ref(A), std::ref(B)) );
return 0;
}

Here's one way, passing just a pair of references (no copying):
#include <utility> // pair
#include <functional> // ref
#include <iostream>
using namespace std;
struct Obj {};
auto foo( pair<Obj const&, Obj const&> const ab )
{
Obj const& a = ab.first;
Obj const& b = ab.second;
cout << &a << " " << &b << endl;
}
auto main() -> int
{
Obj a;
Obj b;
cout << &a << " " << &b << endl;
foo( make_pair( ref( a ), ref( b ) ) );
}
This works nicely because std::make_pair has special support for std::reference_wrapper arguments, then deducing reference to the referred to type.
std::reference_wrapper is the result type of std::ref.

Since std::make_pair supports move semantics, you just need to write your function as you suggested, but when calling it move objects A and B into the std::make_pair as shown below:
// Just as you already suggested
bool foo(const std::pair<Obj, Obj>& A_and_B) {
// do some computation on A & B
}
Call it as:
int main( void )
{
Obj A; // work on A
Obj B; // work on B
auto A_and_B = std::make_pair(std::move(A), std::move(B)); // effectively moves A and B; no copies!
// A and B are now reset, but you can use A_and_B.first and A_and_B.second!
foo( A_and_B );
return 0;
}
Live demo.

Since you are passing the pair by reference, it is not copied. However, Obj A=A_and_B.first will create a copy. If you want to avoid that, you can get a reference to the element, i.e.
Obj &A=A_and_B.first.

Related

Did std::bind implement std::ref and std::cref to disambiguate the function call?

I know that I shouldn't overload a function for just parameters differ only in one of them passed by copy and the other by reference:
void foo(int x)
{
cout << "in foo(int x) x: " << x << endl;
}
void foo(int& x)
{
cout << "in foo(int& x) x: " << x << endl;
}
int main()
{
int a = 1;
foo(5); // ok as long as there is one best match foo(int)
foo(a); // error: two best candidates so the call is ambiguous
//foo(std::move(a));
//foo(std::ref(an)); // why also this doesn't work?
}
So a code that uses std::bind can be like this:
std::ostream& printVec(std::ostream& out, const std::vector<int> v)
{
for (auto i : v)
out << i << ", ";
return out;
}
int main()
{
//auto func = std::bind(std::cout, std::placeholders::_1); // error: stream objects cannot be passed by value
auto func = std::bind(std::ref(std::cout), std::placeholders::_1); // ok.
}
So std::ref here to ensure passing by reference rather than by value to avoid ambiguity?
* The thing that matters me: Does std::bind() implemented some wrapper to overcome this issue?
Why I can't use std::ref in my example to help the compiler in function matching?
Now that you know passing by value and reference are ambiguous when overload resolution tries to compare them for choosing a best viable function, let's answer how would you use std::ref (or std::cref) to differentiate between pass-by-value and pass-by-reference.
It turns out to be ... pretty simple. Just write the overloads such that one accepts a int, and the other accepts a std::reference_wrapper<int>:
#include <functional>
#include <iostream>
void foo(int x) {
std::cout << "Passed by value.\n";
}
void foo(std::reference_wrapper<int> x) {
std::cout << "Passed by reference.\n";
int& ref_x = x;
ref_x = 42;
/* Do whatever you want with ref_x. */
}
int main() {
int x = 0;
foo(x);
foo(std::ref(x));
std::cout << x << "\n";
return 0;
}
Output:
Passed by value.
Passed by reference.
42
The function pass the argument by value by default. If you want to pass by reference, use std::ref explicitly.
Now let's answer your second question: how does std::bind deal with this type of scenario. Here is a simple demo I have created:
#include <functional>
#include <type_traits>
#include <iostream>
template <typename T>
struct Storage {
T data;
};
template <typename T>
struct unwrap_reference {
using type = T;
};
template <typename T>
struct unwrap_reference<std::reference_wrapper<T>> {
using type = std::add_lvalue_reference_t<T>;
};
template <typename T>
using transform_to_storage_type = Storage<typename unwrap_reference<std::decay_t<T>>::type>;
template <typename T>
auto make_storage(T&& obj) -> transform_to_storage_type<T> {
return transform_to_storage_type<T> { std::forward<T>(obj) };
}
int main() {
int a = 0, b = 0, c = 0;
auto storage_a = make_storage(a);
auto storage_b = make_storage(std::ref(b));
auto storage_c = make_storage(std::cref(c));
storage_a.data = 42;
storage_b.data = 42;
// storage_c.data = 42; // Compile error: Cannot modify const.
// 0 42 0
std::cout << a << " " << b << " " << c << "\n";
return 0;
}
It is not std::bind, but the method used is similar (it's also similar to std::make_tuple, which has the same semantic). make_storage by default copies the parameter, unless you explicitly use std::ref.
As you can see, std::ref is not magic. You need to do something extra for it to work, which in our case is to first decay the type (all references are removed in this process), and then check whether the final type is a reference_wrapper or not; if it is, unwrap it.

Lambda-specific variable

Is there any way to create variable that will be unique for some lambda function and will last between launches of lambda?
More careful description: I want lambda with variable initialized to some value, and that variable should last between launches:
std::function<void(void)> a=[]()
{
/*here we declare variable X and initialize it to 0*/;
std::cout<<X++;
};
a();a();
So this should print out 01
But also I need to be sure that "X" is unique for "a", so after previous part this
std::function<void(void)> b=a;
b();b();
should print out 01.
I tried using static variables, but they are shared between copies(so these two parts print out 0123).
So, is there any way to do it?
I don't think mutable lambdas are sufficient. The mutable capture will get copied, when you copy the function pointer, also copying the counter. My read of the question, is that each copy of the lambda should start with the initial mutable capture.
You need to capture a custom class, with a copy constructor, to do this:
#include <functional>
#include <iostream>
class my_class {
public:
int n=0;
my_class()
{
}
my_class(const my_class &b)
{
}
};
int main()
{
std::function<void(void)> a=
[my_class_instance=my_class()]()
mutable
{
std::cout << my_class_instance.n++;
};
a();
a();
auto b=a;
b();
b();
}
The result from this is:
0101
Without a helper class, the equivalent code using only mutable lambdas will produce a
0123
My read of the question, is that the former behavior is desired.
You want it to reset on copies. Make data that does this:
template<class T>
struct no_copy {
T init;
T current;
operator T&(){ return current; }
operator T const&()const{ return current; }
no_copy( T&& i ):init(i), current(init) {}
no_copy( no_copy const&o ):init(o.init), current(init) {}
no_copy( no_copy &&o ):init(std::move(o.init)), current(init) {}
};
template<class T>
no_copy<std::decay_t<T>> make_no_copy(T&& t){
return {std::forward<T>(t)};
}
Then, in C++14, easy:
std::function<void(void)> a=[X=make_no_copy(0)]()mutable
{
std::cout<<X++;
};
a();a();
prints out 01.
In C++11:
auto X=make_no_copy(0);
std::function<void(void)> a=[X]()mutable
{
std::cout<<X++;
};
a();a();
it also works, but is a bit more ugly.
Other than a copy of X existing outside of the lambda, the C++11 version is the same as the C++14 version in behavior.
live example
Is using the copy constructor for "resetting" the only option? Shouldn't you be instead writing a factory function that emits fresh lambdas from the same initial environment?
Expecting that stuff A is different from stuff B after a copy is abuse of semantics.
auto make_counter() -> std::function<int()> {
return [x=0]() mutable { return x++; };
}
auto a = make_counter();
std::cout << a() << " " << a() << "\n";
auto b = make_counter();
std::cout << b() << " " << b() << "\n";

How can I use a vector wrapper class when enclosed in another vector?

Consider a free function from a third part library that expects a std::vector as argument: void foo( std::vector<sometype>& );
Now, I write a wrapper around this type so I can add member functions. To be able to use foo() with that type, I add an access function.
class Wrapper
{
private:
std::vector<sometype> _data;
public:
std::vector<sometype>& data() { return _data; }
const std::vector<sometype>& data() const { return _data; }
//... other stuff
};
This way, I can still use foo():
Wrapper a;
foo( a.data() );
But now consider another function, that expects a vector of vectors of sometype (edit: and that adds elements into that vector) :
void bar( std::vector<std::vector<sometype>>& );
But the datatype I have is std::vector<Wrapper> vec;
Is there any way to use my wrapper type to call bar() ?
What I want to do is this:
std::vector<Wrapper> vec;
bar( ??? );
The point I want to avoid is first call bar() with the required type, and then having to copy one by one the elements into my vector<Wrapper>.
At first, I'd say "No", but maybe there is some smart solution ?
Edit2: to give an example, consider the following toy implementation for bar() with an int root datatype:
void bar( std::vector<std::vector<int>>& vv )
{
std::vector<int> v1 = { 1,2,3 };
std::vector<int> v2 = { 4,5,6 };
vv.push_back(v1);
vv.push_back(v2);
}
[Edited after new comments requiring elements added in the bar function]
A possible solution would be to keep a std::vector<std::vector<sometype>> for the function to use and just operate on a VectorAccessor object referring to the real vectors
#include <iostream>
#include <vector>
struct sometype {
int value;
sometype(int v) : value(v) {}
};
void bar(std::vector<std::vector<sometype>>& par) {
std::cout << "bar() - Before adding new elements:" << std::endl;
for (auto& subvec : par) {
std::cout << "Subvector: {";
for (auto& sometypeItem : subvec) {
std::cout << sometypeItem.value << " ";
}
std::cout << "};" << std::endl;
}
std::vector<sometype> newItem = {32, 33};
par.emplace_back(newItem);
}
class VectorAccessor {
std::vector<std::vector<sometype>>& m_vec;
public:
VectorAccessor(std::vector<std::vector<sometype>>& v) : m_vec(v) {}
template<typename V>
void addVector(V&& vec) {
static_assert(std::is_same<typename std::remove_reference<V>::type,
std::vector<sometype>>::value, "Not the right type");
m_vec.emplace_back(std::forward<V>(vec));
}
std::vector<sometype> accessVector(size_t index) {
return m_vec[index];
}
};
int main(int argc, char ** argv)
{
std::vector<std::vector<sometype>> vec;
VectorAccessor vAcc(vec);
// Add an element through the vector accessor
std::vector<sometype> firstVector = {42};
firstVector.emplace_back(52);
vAcc.addVector(firstVector);
// Call bar and add a few elements
bar(vec);
// Now access stuff with the usual wrapper
std::cout << "Elements added by bar:" << std::endl;
std::cout << "Subvector: {";
for (auto& sometypeItem : vAcc.accessVector(1)) {
std::cout << sometypeItem.value << " ";
}
std::cout << "};" << std::endl;
return 0;
}
Example
Out of the box, calling a function taking a vector<vector<something> won't work with a vector<Wrapper>, because their type is different, and the compiler explicitely expects the former.
I don't think there is any way this form of type substitution could work in C++.
Workaround
There's a workaround to everyhting : you could use conversions in your own code to let the magic happen.
Let me explain.
If the function you intend to use takes a vector<vector<something>>, in C++, you basically have to give it a vector<vector<something>>. So you can't create your vector as a vector<Wrapper> and avoid converting it to a vector<vector<something>>.
On the other hand, you can
use a vector<vector<something> in which you will push instances of Wrapper (using an implicit conversion).
if you need Wrapper functionnality, you can convert your vector<something> using a conversion constructor.
Let's take that example :
#include <iostream>
#include <vector>
using namespace std;
//Templated class wrapper. It does not have to be templated though.
template<typename T>
class Wrapper{
private:
//Here is our inner vector.
vector<T> vect;
public:
//here is our implicit convertion operator :
operator vector<T>& () const {return this->vect;}
//A function so that we can push some stuff in it
void push(T elem){
this->vect.push_back(elem);
}
//here is some additional functionnality in top of vector;
void print(){
int i = 0;
for(i=0;i<this->vect.size();i++){
cout << vect[i] << " ";
}
cout << endl;
}
//this is our very simple conversion constructor
Wrapper<T>(vector<T> vect){
this->vect = vect;
}
//we still need a normal constructor
Wrapper<T>(){}
};
//A function that takes a vector of vectors.
vector<int> concat(vector<vector<int>> vectors){
int i = 0,j=0;
vector<int> result;
for(i=0;i<vectors.size();i++){
for(j=0;j<vectors[i].size();j++){
result.push_back(vectors[i][j]);
}
}
return result;
}
int main()
{
//Let's create an instance of Wrapper and fill it.
Wrapper<int>ex;
ex.push(1);
ex.push(2);
//And yet another one
Wrapper<int>ex2;
ex2.push(5);
ex2.push(6);
//Here we create precisely what the 'concat' function wants:
//namely a vector<vector<int>>.
vector<vector<int>> vectors;
//you can push Wrappers in it, since the conversion will take place.
vectors.push_back(ex);
vectors.push_back(ex2);
//this function call will be successful, since the type of
//vectors is vector<vector<int>>
vector<int> res = concat(vectors);
//Now if you want to use the wrapper functionnality on any
//vector<int>, just convert it on-demand.
//The constructor is extra light-weight in terms of computing power
//as you can see above.
Wrapper<int>(res).print();
Wrapper<int>(vectors[0]).print();
}
P.S. The push_back function will copy the element, so if your function does modify your vector, it won't be reflected on the Wrapper, since it's a copy of its inner vector that has been modified. Using a real vector<something> and push_back would result in the same behaviour.
instead of std::vector<Wrapper> vec;
use
std::vector< std::vector<sometype> > vec;
anyway, you can insert your Wrapper objects into vec
vec.push_back(a.data());
and then call bar(vec);
Ok, so I came up with something that seems to work, although there could be some issues left. The idea is to wrap the vector of vectors into some global wrapper, and then the initial wrapper accessing the data inside it using pointers.
Say with the following toy bar() function:
void bar(std::vector<std::vector<int>>& par)
{
std::vector<int> v1 = { 1,2,3 };
par.push_back(v1);
}
The two wrappers:
struct GlobalWrapper
{
std::vector<std::vector<int>> _data;
size_t size() const { return _data.size(); }
std::vector<int>& Get( size_t i ) { return _data[i]; }
const std::vector<int>& Get( size_t i ) const { return _data[i]; }
};
struct Wrapper
{
std::vector<int>* _data;
void DoSomething() const
{
cout << "values: ";
std::copy( _data->begin(), _data->end(), std::ostream_iterator<int>(std::cout, " "));
}
Wrapper( std::vector<int>& value ) : _data(&value)
{
}
};
And a test program:
int main(int argc, char ** argv)
{
GlobalWrapper gw;
cout << "size before=" << gw.size() << endl;
bar( gw._data );
cout << "size after=" << gw.size() << endl;
Wrapper w = gw.Get(0); // get first element and do something with it
w.DoSomething();
return 0;
}
One issue left: ownership of data. Probably needs some smart pointers.
Running code is here.

std::bind of class member function

I have this code:
#include <iostream>
#include <functional>
struct Foo
{
int get(int n) { return 5+n; }
};
int main()
{
Foo foo;
auto L = std::bind(&Foo::get, &foo, 3);
std::cout << L() << std::endl;
return 0;
}
Seems that this:
auto L = std::bind(&Foo::get, &foo, 3);
is equivalento to:
auto L = std::bind(&Foo::get, foo, 3);
Why?
std::bind() accepts its arguments by value. This means that in the first case you are passing a pointer by value, resulting in the copy of a pointer. In the second case, you are passing an object of type foo by value, resulting in a copy of an object of type Foo.
As a consequence, in the second case the evaluation of the expression L() causes the member function get() to be invoked on a copy of the original object foo, which may or may not be what you want.
This example illustrates the difference (forget the violation of the Rule of Three/Rule of Five, this is just for illustration purposes):
#include <iostream>
#include <functional>
struct Foo
{
int _x;
Foo(int x) : _x(x) { }
Foo(Foo const& f) : _x(f._x)
{
std::cout << "Foo(Foo const&)" << std::endl;
}
int get(int n) { return _x + n; }
};
int main()
{
Foo foo1(42);
std::cout << "=== FIRST CALL ===" << std::endl;
auto L1 = std::bind(&Foo::get, foo1, 3);
foo1._x = 1729;
std::cout << L1() << std::endl; // Prints 45
Foo foo2(42);
std::cout << "=== SECOND CALL ===" << std::endl;
auto L2 = std::bind(&Foo::get, &foo2, 3);
foo2._x = 1729;
std::cout << L2() << std::endl; // Prints 1732
}
Live example.
If, for any reason, you don't want to use the pointer form, you can use std::ref() to prevent a copy of the argument from being created:
auto L = std::bind(&Foo::get, std::ref(foo), 3);
They are not the same. The generic function binder std::bind copies it's arguments. In the case of std::bind(&Foo::get,&foo,3), the pointer is copied, but when you call the bound object it still applies to the original foo object. In std::bind(&Foo::get,foo,3) the object foo is copied, and the later call applies to the bound copy, not to the original object.
You can test this by using a member function that accesses internal state of the object, bind the object in both ways, change the original object and see how the results differ.

member function alternative names

I am trying to create alternative names for the function call numberedFunction when it has certain values as below
template< typename T >
class X
{
public:
X() : single( std::bind( &X::numberedFunction, *this, 1 ) ),
halfDozen( std::bind( &X::numberedFunction, *this, 6 ) )
{ ... }
T numberedFunction( unsigned int i ) { ... }
const std::function< T() >& single;
const std::function< T() >& halfDozen;
};
But this code is not correct (segfaults when I try to use any of the specially named functions). Is there an issue with using this the way I am in the initialization list (e.g., is this not guarenteed to be well-formed at the time I am accessing it there)? Something else (obvious)? Is there a better way to do what I am trying to do (I feel like there almost definitely is)?
const std::function< T() >& single;
const std::function< T() >& halfDozen;
Your members are references to const, but you are initializing them from a temporary in the constructor (assuming the bind expressions in your real code aren't nonsensical). As soon as the construction is done they are invalid. Is this really what you intended?
Maybe this is what you want do do (using psychic powers here):
template< typename T >
class X
{
public:
X() : single( std::bind( &X::numberedFunction, this, 1 ) ),
halfDozen( std::bind( &X::numberedFunction, this, 6 ) )
{ ... }
T numberedFunction( unsigned int i ) { ... }
const std::function< T() > single;
const std::function< T() > halfDozen;
};
Notice that I'm binding to this, not *this. This avoids a copy, but may not be what you want.
An alternative approach is to just add a few forwarding functions:
T numberedFunction( unsigned int i ) { ... }
T single()
{ return numberedFunction(1); }
T halfDozen()
{ return numberedFunction(6); }
You're using this pointer in the initialization list. It's an uninitialized object. I wonder whether you could compile this code successfully or not!
See a sample to see the usage of bind (taken from MSDN)
// std_tr1__functional__bind.cpp
// compile with: /EHsc
#include <functional>
#include <algorithm>
#include <iostream>
using namespace std::placeholders;
void square(double x)
{
std::cout << x << "^2 == " << x * x << std::endl;
}
void product(double x, double y)
{
std::cout << x << "*" << y << " == " << x * y << std::endl;
}
int main()
{
double arg[] = {1, 2, 3};
std::for_each(&arg[0], arg + 3, square);
std::cout << std::endl;
std::for_each(&arg[0], arg + 3, std::bind(product, _1, 2));
std::cout << std::endl;
std::for_each(&arg[0], arg + 3, std::bind(square, _1));
return (0);
}