Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit conversion to explicit bool-types for sorting containers?

I am playing around with the new explicit for cast-operators. If you write something like

struct Data {
    explicit operator string(); 
};

It is not possible to accidentally convert Data to string. The darget data type bool is an exception: In certain cases the implicit conversion is allowed even if it is marked explicit -- contextual conversion. So, you can use this data types in an if(...) for example:

struct Ok {
    explicit operator bool(); // allowed in if(...) anyway
};

The paragraph "25.4.(2) Sorting and related operations" seems to allow this for the Compare functor of standard containers like set as well. But my tries with gcc-4.7.0 fail, and I am note sure if it is my mis-understanding or a bug in gcc?

#include <set>

struct YesNo { // Return value type of Comperator
    int val_;
    explicit YesNo(int y) : val_{y} {}
    /* explicit */ operator bool() { return val_!=0; }
};

static const YesNo yes{1};
static const YesNo no{0};

struct LessYesNo {  // Comperator with special return values
    YesNo operator()(int a, int b) const {
        return a<b ? yes : no;
    }
};

int main() {
    std::set<int,LessYesNo> data {2,3,4,1,2};
}

Without the explicit before operator bool() the example compiles. And my understanding of "25.4.(2)" is, that this should also compile with the `explicit.

Did I understand the Std correctly that for set also explicit bool conversions should work? And might this be a bug in gcc then, or did I understand something wrong?

like image 621
towi Avatar asked Nov 04 '11 17:11

towi


1 Answers

My reading of the standard is a little different - section 25.4 deals with sorting algorithms rather than for sorted containers; the context established in 25.4.(1) means that the property of the compare object specified in 25.4.(2) applies to the algorithms in 25.4, not to sorted containers

1 All the operations in 25.4 have two versions: one that takes a function object of type Compare and one that uses an operator.

2 Compare is a function object type (20.8). The return value of the function call operation applied to an object of type Compare, when contextually converted to bool (4), yields true if the first argument of the call is less than the second, and false otherwise. Compare comp is used throughout for algorithms assuming an ordering relation. It is assumed that comp will not apply any non-constant function through the dereferenced iterator.

I don't know whether your example should work or not, but I don't think section 25.4 is applicable here.

A quick test with a vector and std::sort works:

#include <list>
#include <algorithm>

struct YesNo { // Return value type of Comperator
    int val_;
    explicit YesNo(int y) : val_{y} {}
    explicit operator bool() { return val_!=0; }
};

static const YesNo yes{1};
static const YesNo no{0};

struct LessYesNo {  // Comperator with special return values
    YesNo operator()(int a, int b) const {
        return a<b ? yes : no;
    }
};

int main() {
    std::vector<int> data {2,3,4,1,2};
    std::sort(std::begin(data), std::end(data), LessYesNo());
}

Edit:

The associative container's Compare parameter is defined in terms of secion 25.4:

1 Associative containers provide fast retrieval of data based on keys. The library provides four basic kinds of associative containers: set, multiset, map and multimap.

2 Each associative container is parameterized on Key and an ordering relation Compare that induces a strict weak ordering (25.4) on elements of Key. In addition, map and multimap associate an arbitrary type T with the Key. The object of type Compare is called the comparison object of a container.

and 23. has no other conditions on the type of Compare as far as I can see, so it does seem reasonable to assume that a type satisfying the constraints of 25.4 are equally applicable.

like image 75
je4d Avatar answered Oct 20 '22 00:10

je4d