Search code examples
c++boostboost-signals2

boost::signals2::signal gives wrong output?


I'm new to boost library, while practicing an example on bind, i wrote the following code. But, it seems like the 'res' is computed properly but, the correct result is not transmitted back to the signal. Kindly help, what is wrong in the following snippet. The code was compiled and run on http://cpp.sh/

#include <iostream>
#include<boost/signals2.hpp>

using namespace std;
class MathObject{
public:
    int AddOps(int op1, int op2);
};

int MathObject::AddOps(int op1, int op2){
    int res = op1 + op2;
    cout << "Result of AddOps: " << res << endl;
    return res;
}

int main(void){
    MathObject mObj;
    boost::signals2::signal<int(int)> incrementer;
    incrementer.connect(boost::bind(&MathObject::AddOps, &mObj, 1, _1));
    boost::signals2::signal<int(int)> doubler;
    doubler.connect(boost::bind(&MathObject::AddOps, &mObj, _1, _1));
    cout << "Incrementer of 5" << incrementer(5) << endl;
    cout << "Doubler of 5" << doubler(5) << endl;
}

Output:

Result of AddOps: 6
Incrementer of 51
Result of AddOps: 10
Doubler of 51

Solution

  • When a signal is called, it may or may not have any handlers connected to it. Therefore it may or may not produce a result. The default behaviour is to return the result of the last-connected handler, if any; or to return a value indicating "no result". Thus the return value of incrementer(5) and doubler(5) is not an int, but rather a boost::optional<int>.

    This leads to the output that you observe because a boost::optional<int> can be implicitly converted to bool, which is then converted to an output of 1 or 0.

    You need to first check that a result is present, and then get the result out of the boost::optional<int> that is returned:

    #include <iostream>
    #include<boost/signals2.hpp>
    
    using namespace std;
    class MathObject{
    public:
        int AddOps(int op1, int op2);
    };
    
    int MathObject::AddOps(int op1, int op2){
        int res = op1 + op2;
        cout << "Result of AddOps: " << res << endl;
        return res;
    }
    
    int main(void){
        MathObject mObj;
        boost::signals2::signal<int(int)> incrementer;
        incrementer.connect(boost::bind(&MathObject::AddOps, &mObj, 1, _1));
        boost::signals2::signal<int(int)> doubler;
        doubler.connect(boost::bind(&MathObject::AddOps, &mObj, _1, _1));
        boost::optional<int> incremented = incrementer(5);
        if (incremented) {
            cout << "Incrementer of 5: " << *incremented << endl;
        }
        boost::optional<int> doubled = doubler(5);
        if (doubled) {
            cout << "Doubler of 5: " << *doubled << endl;
        }
    }