Question

Could somebody please tell me why I am getting compiler error for the last line of the following code?

note: If I remove the following line, my code gets compiled with no error:

appliedEqualityVisitor(compareValue);

Here is the code:

#include "boost/variant/variant.hpp"
#include "boost/variant/apply_visitor.hpp"

using namespace std;
using namespace boost;


template<typename T>
struct CheckOneTypeEquality : public boost::static_visitor<>
{
    T const* value;
    bool operator()( T const& other ) const
    {
        return other == *value;
    }
    template<typename U>
    bool operator()( U const& other ) const
    {
        return false;
    }
    CheckOneTypeEquality( T const& value_ ):value(&value_) {}
};

typedef variant<int, string> MyVariant;
typedef apply_visitor_delayed_t<CheckOneTypeEquality<MyVariant>> AppliedEqualityVisitorType;

int main(int argc, char **argv) 
{
    int testValue = 12;
    CheckOneTypeEquality<MyVariant> equalityVisitor(testValue);

    AppliedEqualityVisitorType appliedEqualityVisitor = apply_visitor(equalityVisitor);

    MyVariant compareValue = 13;
    appliedEqualityVisitor(compareValue); // <<<<< compile error here

    return 0;
}
Was it helpful?

Solution

The problem stems from your visitor class. Boost expects a void operator()(...), instead you provide an operator() that returns something.

For your pattern to work, you will have to change the visitor, something like:

template<typename T>
struct CheckOneTypeEquality : public boost::static_visitor<>
{
    T const* value;
    mutable bool check;
    void operator()( T const& other ) const
    {
        check = other == *value;
    }
    template<typename U>
    void operator()( U const& other ) const
    {
      check = false;
    }
    CheckOneTypeEquality( T const& value_ ):value(&value_), check(false) {}
};

Then test the result. Btw. am not sure that your constructor there to which you pass an int is safe. You are not holding the reference, rather pointing to a temporary instance of the variant which is constructed from the int - which may be out of scope.

EDIT: I think what you are trying to do is misguided, given that boost::variant already implements operator== correctly. For example:

MyVariant testValue = 12;

MyVariant compareValue = 13;
MyVariant compareValue2 = 12;
MyVariant compareValue3 = "12";

std::cout << (compareValue == testValue) << std::endl;
std::cout << (compareValue2 == testValue) << std::endl;
std::cout << (compareValue3 == testValue) << std::endl;

Works fine - and I think it is what you are trying to accomplish? You want to test that two variants are equally comparable(?) This will work as long as all the objects in your variant are equally comparable.

OTHER TIPS

About:

But when I call appliedEqualityVisitor(compareValue) it always returns false, no matter what the compareValue is. Any idea?

I think that you misunderstood the usage of visitors, the operator () is invoked with the actual variant type not with a variant parameter (int in your example).

EDIT: in the code

int testValue = 12;
CheckOneTypeEquality<MyVariant> equalityVisitor(testValue);

the testValue is converted to MyVariant when instantiating the visitor.

an boost example of equality boost link

class are_strict_equals
    : public boost::static_visitor<bool>
{
public:

    template <typename T, typename U>
    bool operator()( const T &, const U & ) const
    {
        return false; // cannot compare different types
    }

    template <typename T>
    bool operator()( const T & lhs, const T & rhs ) const
    {
        return lhs == rhs;
    }

};

boost::variant< int, std::string > v1( "hello" );

boost::variant< double, std::string > v2( "hello" );
assert( boost::apply_visitor(are_strict_equals(), v1, v2) );

boost::variant< int, const char * > v3( "hello" );
assert( !boost::apply_visitor(are_strict_equals(), v1, v3) );

The

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top