(I have read What is the lifetime of lambda-derived implicit functors in C++? already and it does not answer this question.)
I understand that C++ lambda syntax is just sugar for making an instance of an anonymous class with a call operator and some state, and I understand the lifetime requirements of that state (decided by whether you capture by value of by reference.) But what is the lifetime of the lambda object itself? In the following example, is the std::function instance returned going to be useful?
std::function<int(int)> meta_add(int x) {
auto add = [x](int y) { return x + y; };
return add;
}
If it is, how does it work? This seems a bit too much magic to me - I can only imagine it working by std::function copying my whole instance, which could be very heavy depending on what I captured - in the past I've used std::function primarily with bare function pointers, and copying those is quick. It also seems problematic in light of std::function's type erasure.
The lifetime is exactly what it would be if you replaced your lambda with a hand-rolled functor:
struct lambda {
lambda(int x) : x(x) { }
int operator ()(int y) { return x + y; }
private:
int x;
};
std::function<int(int)> meta_add(int x) {
lambda add(x);
return add;
}
The object will be created, local to the meta_add function, then moved [in its entirty, including the value of x] into the return value, then the local instance will go out of scope and be destroyed as normal. But the object returned from the function will remain valid for as long as the std::function object that holds it does. How long that is obviously depends on the calling context.
It seems you're more confused about std::function than lambdas.
std::function uses a technique called type-erasure. Here's a quick fly by.
class Base
{
virtual ~Base() {}
virtual int call( float ) =0;
};
template< typename T>
class Eraser : public Base
{
public:
Eraser( T t ) : m_t(t) { }
virtual int call( float f ) override { return m_t(f); }
private:
T m_t;
};
class Erased
{
public:
template<typename T>
Erased( T t ) : m_erased( new Eraser<T>(t) ) { }
int do_call( float f )
{
return m_erased->call( f );
}
private:
Base* m_erased;
};
Why would you want to erase the type? Isn't the type we want just int (*)(float)?
What the type erasure allows is Erased can now store any value that is callable like int(float).
int boring( float f);
short interesting( double d );
struct Powerful
{
int operator() ( float );
};
Erased e_boring( &boring );
Erased e_interesting( &interesting );
Erased e_powerful( Powerful() );
Erased e_useful( []( float f ) { return 42; } );
This is:
[x](int y) { return x + y; };
Is equivalent to: (Or can be considered too)
struct MyLambda
{
MyLambda(int x): x(x) {}
int operator()(int y) const { return x + y; }
private:
int x;
};
So your object is returning an object that looks just like that. Which has a well defined copy constructor. So it seems very reasonable that it it can be correctly copied out of a function.
In the code that you posted:
std::function<int(int)> meta_add(int x) {
auto add = [x](int y) { return x + y; };
return add;
}
The std::function<int(int)> object that is returned by the function actually holds a moved instance of the lambda function object that was assigned to local variable add.
When you define a C++11 lambda that captures by-value or by-reference, the C++ compiler automatically generates a unique functional type, an instance of which is constructed when the lambda is called or assigned to a variable. To illustrate, your C++ compiler might generate the following class type for the lambda defined by [x](int y) { return x + y; }:
class __lambda_373s27a
{
int x;
public:
__lambda_373s27a(int x_)
: x(x_)
{
}
int operator()(int y) const {
return x + y;
}
};
Then, the meta_add function is essentially equivalent to:
std::function<int(int)> meta_add(int x) {
__lambda_373s27a add = __lambda_373s27a(x);
return add;
}
EDIT: By the way, I am not sure if you know this, but this is an example of function currying in C++11.
Related
I am looking to accomplish the following:
int x, y, z;
foo[x] = y; acts like do_this(x,y);
z = foo[x]; acts like z = do_that(x)
I can accomplish the first with a Foo class and a Helper class, where the operator[] returns by value a Helper class constructed with x, and the operator= for the Helper class is defined to run do_this(this->x, y). Like below:
class Foo {
public:
Helper operator[](int x) {
return Helper(x);
}
};
class Helper {
public:
Helper(x) {
this->x = x;
}
void operator=(int y) {
do_this(this->x, y);
}
private:
int x;
};
What I can't figure out is how to accomplish (2). Is there a way to overload the operator[] so that it knows if it was used on the lhs vs the rhs?
Yes - give your Helper class a conversion function to int:
class Helper {
public:
Helper(x){
this->x = x;
}
Helper& operator= (int y) {
do_this(this->x, y);
return *this;
}
operator int() const {
return do_that(this->x);
}
private:
int x;
};
This will also allow other uses like product *= foo[x]; or func_taking_int(foo[x]), etc.
One potential catch is that some uses of auto or function templates would still just keep the type Helper, which might not be what's wanted - so users of Foo should still understand that this proxy sugar is going on. It could also be helpful to have some alternative syntax to explicitly get the int value for cases like that, in either Foo or Helper.
I'm not sure I've understood what you actually want to do, but you are might be able to use the const version of the operator[] vs. the non-const version. For example:
struct Foo {
Z operator [] (int x) const { // this last const is important
return do_that(x);
}
Helper operator [] (int x) {
// as you yourself have written.
}
};
There are more tips and tricks to this, for forwarding arguments perfectly (a.k.a "perfect forwarding",) for being "const correct", and many other small things, but the gist of it is the above.
I have started to learn about lambda expressions and nested lambda expressions:
auto Suma=[](int x)->function<int(int)>
{
return [x](int y)
{
return x+y;
};
};
auto Mult=[](function<int(int)>&f, int z)
{
return f(z)*2;
};
I would like to create 3 Functor classes (for better understanding how it works), it should be 3 classes Sum, Inner and Mult.
.h:
class Suma
{
public:
int operator()(int x);
};
class Inner
{
Suma function;
public:
Inner(int x);
int operator()(int k);
};
class Mult
{
public:
int operator()(Suma function,int z);
};
.cpp:
int Suma::operator()(int x)
{
return x;
}
Inner::Inner(int x)
{
function.operator()(x);
}
int Inner::operator()(int k)
{
return function.operator()+k;
}
int Mult::operator()(Suma function,int z)
{
return (function.operator())*(2);
}
The main issue I face is when trying to include the function from one related class to another. I dont fully understand the main idea of how it is connected through classes. Could please advice me how should it work.
Your classes do not reflect the structure of the lambdas.
The inner lambda returns a function with adds its paramter to the capture.
So your Inner class shall not depend on Suma, and be defined as follows:
// definition in .h
class Inner
{
int myx;
public:
Inner(int x); // this represents the capture of the lambda
int operator()(int k); // this is the function of adding k to the catpture
};
// implementation in .cpp
Inner::Inner(int x)
{
myx = x;
}
int Inner::operator()(int k)
{
return myx + k;
}
The Suma shall then return an Inner with an x set:
// definition in .h
class Suma
{
public:
Inner operator()(int x);
};
// implementation in .cpp
Inner Suma::operator()(int x)
{
return Inner(x);
};
With your lambdas, when you evaluate Suma(3), you'll obtain a function that takes an integer and adds 3 to it. If you evaluate Suma(3)(2) you therefore get 5.
With the classes emulating the lambdas, you would then do the same:
Suma f; // that is an object, like "auto suma"
cout << f(3)(2) <<endl; // f(3) is in fact an object Inner(3) wich is then exectued with argument 2.
Here you have an online demo.
You could even be closer to the structure of your lambdas by having Inner be a nested class of Suma.
Now looking at the Mult class, it appears that the first argument is not a Suma object, but the result of an invocation to Suma (i.e. return type of its operator()) . So it's an Inner. Hence, you can complete the code as follows:
// definition in .h
class Mult {
public:
int operator()(Inner& function, int z);
};
// implementation in .cpp
int Mult::operator()(Inner& function, int z)
{
return (function(z))*(2); // funtion(z) means function.operator()(z)
}
By the way, as you see above, you don't need to explicitely call operator(): just provide the arguments between parenthesis.
For example, I have this code.
#include <iostream>
using namespace std;
int main()
{
int x = 5; //Original variable
int &y = x; //Reference variable to x.
y = 10; //Modifying reference variable.
cout<<x<<" "<<y<<endl;
x = 5; //Modifying original variable.
cout<<x<<" "<<y<<endl;
}
It gives the expected output.
10 10
5 5
Shows that modifying either the original variable or the reference variable changes them both - Pretty obvious.
My question is that:
Can a reference variable be defined in such a way that modifying it DOES NOT modify the original variable?
I know then it wouldn't be called a reference variable.
To make things more clear,
Modifying x should modify y, but modifying y should not modify x. That is, y should be an independent copy of x, but should change as and when x changes.
Can this be possible?
Yes, I can create my own logic to emulate this, but I was wondering if C++ catered to this by default.
There is no language construct that can immediately give you what you seek but you can implement it fairly straightforward by encapsulating x and y.
struct XChangesY{
set_x(int x_and_y){ y = x = x_and_y; }
set_y(int y_){ y = y_; }
int get_x(){ return x; }
int get_y(){ return y; }
private:
int x;
int y;
}
No, what you want to do isn't possible. Consider what happens if you modify both y and x. Where does y take its value then? From the updated value of x which should modify both x and y, or from the updated value of y which should update y only and not x?
The only way forward is to implement your own logic. In any case, you need to have two int variables.
Sure, but it's not elegant--
template<typename T>
class C
{
public:
C(T t) : m_t(new T(t)), t_local(t), is_copy(false) {}
C(const C& c) : m_t(c.m_t), t_local(t), is_copy(true) {}
T Get() { return *m_t; }
T GetLocal() { return t_local; }
void Set(T t)
{
t_local = t;
if (!is_copy) *m_t = t;
}
private:
T* m_t;
T t_local;
bool is_copy;
};
And your setup creates an ambiguity when it comes to evaluating y, after both it has been changed--do you want the value of x, or the new, different value of y? I don't see any way to avoid creating separate methods for each case.
C++ does not provide a mechanism for doing this automatically, but you can make a class that supports the behavior that you are trying to make.
Here is a grossly oversimplified version of what you can do:
class IntRef {
int *ptr;
int copy;
public:
IntRef(int& d) : ptr(&d) {}
IntRef& operator=(const int& rhs) {
// Detach from the original on assignment
copy = rhs;
ptr = ©
}
operator int() const {
return *ptr;
}
};
int main() {
int x = 5; //Original variable
IntRef y(x); //Reference variable to x.
x = 5; //Modifying original variable.
cout<<x<<" "<<y<<endl;
y = 10; //Modifying reference variable.
cout<<x<<" "<<y<<endl;
return 0;
}
Demo.
This prints
5 5
5 10
The idea of the implementation above is to keep a pointer pointing to the original value for as long as y is not assigned. After the assignment the pointer is switched to a copy that is kept internally.
What you're looking for isn't inherently built-in the language - having two variables sharing the same value, changing one changes both but changing the other one only changes one.
That question though is similar to shared pointers and reference counters. For example, when you make a copy of a std::string, the content of the string isn't copied. A new string object is created with a pointer to the same data as the first string, and a reference counter.
So both strings share the same data. But when you change one - either one - and the reference counter is more than one, then that string dissociates itself and copies the data, and both strings are no longer linked. This is in order to avoid duplicated long strings of data when there's no need.
The same thing happens with Qt containers (QByteArray, QMap, QList, ...).
Another way to look at your problem is a logic of watcher - data received from outside updates the internal value, but the internal value can be changed by other means. Qt's signals/slot feature can be used to do that naturally, or you can easily implement your own logic to do that yourself.
Seems like what you want is copy-on-write semantics. Something like this might work for you, but is easily abused:
template <class T>
class cow_ptr
{
public:
using ref_ptr = std::shared_ptr<T>;
private:
ref_ptr m_sp;
bool m_original; //don't detach the original
void detach()
{
T* tmp = m_sp.get();
if( !( tmp == 0 || m_sp.unique() || m_original ) ) {
m_sp = ref_ptr( new T {*tmp} );
}
}
public:
cow_ptr(T* t)
: m_sp{t}, m_original{true}
{}
cow_ptr(const ref_ptr& refptr)
: m_sp{refptr}, m_original{true}
{}
cow_ptr(const cow_ptr& cowptr)
: m_sp{cowptr.m_sp}, m_original{false}
{}
cow_ptr& operator=(const cow_ptr& rhs)
{
m_sp = rhs.m_sp;
return *this;
}
const T& operator*() const
{
return *m_sp;
}
T& operator*()
{
detach();
return *m_sp;
}
const T* operator->() const
{
return m_sp.operator->();
}
T* operator->()
{
detach();
return m_sp.operator->();
}
};
Then you can use it like this:
int main()
{
auto x = cow_ptr<int>{ new int{5} };
auto y = x;
const auto &yr = y; //so dereferencing doesn't detach
cout<<*x<<" "<<*yr<<endl; //5 5
*x = 10;
cout<<*x<<" "<<*yr<<endl; //10 10 (updating x updated y)
*y = 15;
cout<<*x<<" "<<*yr<<endl; //10 15 (updating y did not update x)
//from now on, changing x will not change y
}
I am trying to specialize std::unordered_map for a class X with a custom hash and a custom equality. The problem is that both the equality and hash functions do not depend only on the object(s) of class X but also on data in another (fixed) object of another class Y. Here is a toy example (with only the hash function) of what I want to do:
#include <unordered_map>
using namespace std;
struct Y {
bool b;
struct X {
size_t i;
};
size_t hash(const X &x) {
return x.i + b;
}
unordered_map<X, int, hash> mymap;
};
The problem is that the function hash in the template specialization is a method and the compiler complains ("call to non-static member function without an object argument"). What I want is that y.mymap uses y.hash(). Any way to do this?
Note that in the real code Y is also a template, in case it matters.
Thanks!
EDIT: To clarify, instead of the boolean b in my code I have a vector with data that is needed in comparing objects of type X. Some data is added when an X is created, so the vector is not constant, but the data for a given X does not change after it is added, so the hash for a given X never changes (so in a sense it depends only on X as required for a hash). The main reason I use this approach is to save memory since this data is a lot and is usually shared.
You can use function<size_t(X const&)> and e.g. bind, but as type erasure is not necessary in this case, here is a simpler solution:
struct Y {
bool b;
struct X {
size_t i;
bool operator==(X x) const {return i == x.i;}
};
size_t hash(const X &x) {
return x.i + b;
}
struct Hasher {
Y* this_;
template <typename T>
auto operator()(T&& t) const
-> decltype(this_->hash(std::forward<T>(t))) {
return this_->hash(std::forward<T>(t));
}
};
unordered_map<X, int, Hasher> mymap;
Y() : b(false),
mymap(0, {this}) {}
};
As mentioned by #dyp in the comments, you have to be careful with special member functions since we implicitly store this in mymap - i.e. the compiler-generated definitions would copy the this_ pointer. An example implementation of the move constructor could be
Y(Y&& y) : b(y.b), mymap(std::make_move_iterator(std::begin(y.mymap)),
std::make_move_iterator(std::end (y.mymap)), 0, {this}) {}
Unfortunately what you want to do is not legal. See 17.6.3.5/Table 26:
h(k) The value returned shall depend only on the argument k.
It's pretty clear that you aren't allowed to have the hash depend on a member of Y as well as X.
EDIT: Just in case you meant for b to be const in your Y class there is a solution (I didn't compile this yet, I will if I get a chance):
struct Y
{
explicit Y(bool config) : b(config), hash_(config), mymap(0, hash_) { }
const bool b;
struct X
{
size_t i;
};
struct Hash
{
explicit Hash(bool b) : b_(b) { }
size_t operator()(const X& x) const
{
return x.i + b_;
}
private:
bool b_;
};
Hash hash_;
unordered_map<X, int, Hash> mymap;
};
I'm using two 3rd party libraries, which both implement their own 2D vector class. Unfortunately, I have to work with both of them, so is there anyway I can write some "friend" functions so that one can automatically be converted to the other when I try to use them in functions from the other library?
Auto-cast seems not to be possible. You could define global conversion function and call it explicitly. Could you post definition of that classes? May be some trick with inheritance will be possible.
Something like this, but it is not auto-cast:
class T1 {};
class T2 {};
class UnionType : public T1, public T2
{
public:
UnionType( const T1& val ) {} // real storing should be here
UnionType( const T2& val ) {} // real storing should be here
operator T1() { T1 t; return t; } // real conversion should be here
operator T2() { T2 t; return t; } // real conversion should be here
};
int main()
{
T1 t;
T2 t2 = UnionType(t);
return 0;
}
Conversion operators have to be member functions.
In situations like this, I have used a convert<X,Y> function template, with full specialisations or overloads for each pair of types that I want to "cast". In this case, you wouldn't need the template, just two overloads, one in each direction, because for a given X there's only ever one thing you convert it to.
Then it's rarely any trouble to switch between one and the other (the notable exception being when you're using template code which requires that one parameter type be convertible to another). You can easily see in the code the boundary between the two APIs, without introducing much noise.
The reason I've had this situation a lot is writing OS abstraction layers - the underlying OS has one set of objects or opaque handles for various OS concepts, and the API you're implementing has another. It's much nicer to just "convert" from one set of concepts to the other, without having ConvertHostMutexToGuestMutex, ConvertGuestMutexToHostMutex, ConvertHostSocketOptsToGuestSocketOpts etc. The disadvantage is the usual one with widespread overloading, that it's not necessarily obvious where the functions are actually defined.
One way would be to derive from those classes and provide conversion operators for one another. But then you have to use the derived class objects through out your code. Here is some sample code:
class ThirdParty1
{
public:
ThirdParty1(int x, int y) : m_x(x), m_y(y)
{
}
int getX() const { return m_x; }
int getY() const { return m_y; }
private:
int m_x;
int m_y;
};
class ThirdParty2
{
public:
ThirdParty2(int x, int y) : m_x(x), m_y(y)
{
}
int getX() const { return m_x; }
int getY() const { return m_y; }
private:
int m_x;
int m_y;
};
template<class Type, class AdaptedType>
class TP1Adaptor : public Type
{
public:
TP1Adaptor(int x, int y): Type(x,y)
{
}
operator AdaptedType()
{
return AdaptedType(getX(),getY());
}
};
typedef TP1Adaptor<ThirdParty1, ThirdParty2> First2D;
typedef TP1Adaptor<ThirdParty2, ThirdParty1> Second2D;
void f(ThirdParty1 tp)
{
}
void f1(ThirdParty2 tp)
{
}
int main()
{
First2D f(0,0);
f1(f);
return 0;
}