Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this legal to avoid set from creating actual copies of Comparator object

In such a code:

Comparator comp(3);

set<string, Comparator> s1(comp);
set<string, Comparator> s2(comp);
set<string, Comparator> s3(comp);
set<string, Comparator> s4(comp); 

the actual instance of the Comparator (namely comp) is copied at each creation of a set object as the cpp reference states

The container keeps an internal copy of alloc and comp, which are used to allocate storage and to sort the elements throughout its lifetime.

So we were wondering if this is legal in C++

#include <set>
#include <iostream>

struct A {
    int i = 0;
    bool operator()(int a, int b)
    {
        ++i;
        return a < b;
    }
};

int main()
{    
    A a;
    std::set<int, A&> s1( {1, 2, 3}, a);
    std::set<int, A&> s2( {4, 5, 6}, a);
    std::cout << a.i;
}

Thanks in advance.

like image 660
Issam T. Avatar asked Oct 02 '22 02:10

Issam T.


1 Answers

I'm unable to find wording in the standard forbidding using a reference type as the comparison function. Thus it seems that this would be legal. Note that some things, such as default constructing such a set, will be forbidden because your comparison type is not default constructable.

Finally note that the canonical C++ approach is to not do this, but to maintain the state externally. When you take that approach it's totally clear what you're doing and guaranteed to be safe:

#include <set>
#include <iostream>

struct A {
    int& i_;
    explicit A(int& state) : i_(state) { }
    bool operator()(int a, int b)
    {
        ++i_;
        return a < b;
    }
};

int main() {
    int i;
    std::set<int, A> s1( {1, 2, 3}, A(i));      
    std::set<int, A> s2( {4, 5, 6}, A(i));        
    std::cout << i << endl;
}
like image 82
Mark B Avatar answered Oct 03 '22 15:10

Mark B