Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Connecting three different objects

I asked a similar question a couple of hours ago about connecting two elements of a vector. Now, I would like to make my question more general. Let's assume that we have two objects of the type double namely double d1, d2. We want the third object (double d3) to obtain the value of d1+d2, such that if we change d1 or d2, then d3 automatically obtains the new value of d1+d2. How can we do it in C++?

This is what I mean:

int main(){
double d1,d2,d3;
d1=4;
d2=7;

//some operations to make d3=d1+d2

std::cout<<d3<<endl;// I want it to print 11
d2=-4;
std::cout<<d3<<endl;//Now without any further operations between these line, it should print 0
return 0;     
}

Thanks.

like image 788
Eman Avatar asked Apr 30 '16 14:04

Eman


People also ask

What allows you to combine multiple objects to behave like one?

Using Draw, you can combine drawing objects together in two distinct ways: grouping and combining. These two methods allow you to treat multiple objects as one unit, or to merge objects to form a new shape. Grouping is like putting objects in a container. You can move them as a group and apply global changes to them.

What is the interaction between two objects?

An interaction between two objects which causes a push or pull is termed as force.


Video Answer


3 Answers

You can create a wrapper, as a lambda:

double d1 = 0, d2 = 0;
auto l = [&](){ return d1 + d2; };

l(); // 0
d1 = 40;
d2 = 2;
l(); // 42

If you want that all the variables has the same type, you may add a type-erasure wrapper as std::function:

std::function<double()> f1 = [] { return 0; };
std::function<double()> f2 = [] { return 0; };
std::function<double()> sum = [&] { return f1() + f2(); };

std::cout << sum() << std::endl; // 0
f1 = [] { return 40; };
f2 = [] { return 2; };

std::cout << sum() << std::endl; // 42
like image 185
Jarod42 Avatar answered Oct 02 '22 12:10

Jarod42


Your problem is the classical motivation for parameter binding.

#include <iostream>
#include <functional>

//generic add
template <typename T>
void Add(T x, T y, T & z){
  z = x + y;
}

int main(){

  //z will change automatically in function call
  double z = 0;

  //bind z as the result
  using namespace std::placeholders;
  auto add = std::bind(Add<double>, _1, _2, std::ref(z));

  //z is implicity passed and changed
  add(6,4);

  //outputs 10
  std::cout << z << '\n';
}

bind and reference wrappers can help achieve the functionality you are after.

like image 44
Trevor Hickey Avatar answered Oct 02 '22 12:10

Trevor Hickey


Write a wrapper, which will store pointers to doubles (as recommended in your original question). Beware, that this will not work, if doubles will go out of scope but counter would not. Also, you can overload conversion to T operator to get rid of total() function.

template<typename T>
class counter
{
public:
    void regist(T& d)
    {
        refs.push_back(&d);
    }

    T total()
    {
        T total{};
        for (auto d : refs)
            total += *d;
        return total;
    }

private:
    std::vector<T*> refs;
};

int main(int argc, char* argv[])
{
    double d1 = 1.6;
    double d2 = 7.2;
    double d3 = 1e-4;
    counter<double> cnt;
    cnt.regist(d1);
    cnt.regist(d2);
    cnt.regist(d3);
    std::cout << cnt.total() << std::endl; // 8.8001
    d2 = -7.1;
    std::cout << cnt.total() << std::endl; // -5.4999
}
like image 39
Zereges Avatar answered Oct 02 '22 12:10

Zereges