Friday, April 29, 2011

std::set filled with boost::variant elements cannot be sorted descendantly ??

typedef boost::variant<long long,double,string> possibleTypes ;

set<possibleTypes,less<possibleTypes> > ascSet ;
set<possibleTypes,greater<possibleTypes> > descSet ;

When I try to compile I get a bunch of errors in some library headers.
But, if I remove the third line (the one with descSet ) the code compile just fine.

What's the problem? Can't boost::variant objects be sorted in descendant order??

Edit:
I'm using Visual Studio 2005 and Boost 1.38.0 and the following command line:

cl /EHsc /I"C:\boost_1_38_0" test.cpp

Edit2 As it was suggested, by Doug T, if I define this:

bool operator>(const possibleTypes& a, const possibleTypes& b){
   return b < a ;
}

Then the following code doesn't compile:

possibleTypes pt1="a", pt2="b" ;
greater<possibleTypes> func ;   
cout << func(pt1,pt2) << endl ;

However, this code compiles just fine:

possibleTypes pt1="a", pt2="b" ;
cout << (pt1 > pt2) << endl ;

Could anyone help me to understand why??

I tried with VC++ 2005 and GCC 3.4.6

From stackoverflow
  • It appears a < operator is defined for boost::variant but not a > operator. Thus perhaps std::less<> works but not std::greater<>

    See here

    I would try defining a a free > operator.

    bool operator > (boost::variant<...> lhs, boost::variant<..> rhs)
    {
        return (rhs < lhs) // thanks Chris Jester Young
    }
    
    Chris Jester-Young : Why not just: return rhs < lhs
    Doug T. : yeah that would be simpler, wouldn't it :)
  • Why have two sets? Why not have just one and use a reverse iterator when you need descending order?

    GetFree : I need the ascendant order to avoid changing existing code (written by others). And the two sets are just for testing.
  • You need to have the greater operator available. If possibleTypes does not provide one, you can either define a free one like Doug suggested or try to use Boost operators.

  • As it was suggested, if I define this:

    bool operator>(const possibleTypes& a, const possibleTypes& b){
       return b < a ;
    }
    

    Then the following code doesn't compile:

    possibleTypes pt1="a", pt2="b" ;
    greater<possibleTypes> func ;   
    cout << func(pt1,pt2) << endl ;
    

    However, this code compiles just fine:

    possibleTypes pt1="a", pt2="b" ;
    cout << (pt1 > pt2) << endl ;
    

    Could anyone help me to understand why??

    I tried with VC++ 2005 and GCC 3.4.6

    Max Lybbert : Try defining operator> in namespace boost: namespace boost { bool operator>(const possibleTypes& a, const possibleTypes& b) ... }. The compiler's looking in the wrong place for the operator>, although personally I would expect it to look at any operator> taking two possibleType arguments.
    MSalters : Nope - Argument-dependent lookup. It's not going to search everywhere, it looks in the namespace of the caller (std::greater) and the namespace of the arguments (boost::variant). In the second case, the namespace of the caller is (probably) the global namespace.
    GetFree : Thanks, Max. The problem was fixed adding operator> to the boost namespace. And thanks, MSalters, for clarifying the rules.

0 comments:

Post a Comment