C++11 初始化器\u列表std::set的初始化<;我的班级>;使用平凡运算符<;。gcc中的错误+;/标准图书馆?

C++11 初始化器\u列表std::set的初始化<;我的班级>;使用平凡运算符<;。gcc中的错误+;/标准图书馆?,c++11,gcc,operators,initializer-list,stdset,C++11,Gcc,Operators,Initializer List,Stdset,这就是我的代码的样子 #include <iostream> #include <set> using namespace std; enum Enum_type { Enum_type_1 = 1, Enum_type_2, Enum_type_3, Enum_type_4 }; class my_class { public: my_class(Enum_type type) : source_type(

这就是我的代码的样子

#include <iostream>
#include <set>
using namespace std;

enum Enum_type 
{
    Enum_type_1 = 1,
    Enum_type_2,
    Enum_type_3,
    Enum_type_4
};

class my_class
{
public:

    my_class(Enum_type type) :
        source_type(type)
    {}

    bool operator<(const my_class &another) const;

    Enum_type source_type;
};

bool my_class::operator<(const my_class& another) const
{
    return true;
}

int main()
{
    std::set<my_class> bracers_initialized_set {
        my_class{Enum_type_1},
        my_class{Enum_type_2},
        my_class{Enum_type_3},
        my_class{Enum_type_4}};

    cout<< "bracers_initialized_set.size() " <<  bracers_initialized_set.size() <<endl;
    for (auto my_class_ : bracers_initialized_set) {
        cout << "enum value: " << my_class_.source_type << endl;
    }
    cout<< "bracers_initialized_set.size() " <<  bracers_initialized_set.size() <<endl;

    std::set<my_class> inserted_set;
    if (inserted_set.insert(my_class(Enum_type_1)).second) {
        cout << "inserted_1" << endl;
    }
    if (inserted_set.insert(my_class(Enum_type_2)).second) {
        cout << "inserted_2" << endl;
    }   
    if (inserted_set.insert(my_class(Enum_type_3)).second) {
        cout << "inserted_3" << endl;
    }
    if (inserted_set.insert(my_class(Enum_type_4)).second) {
        cout << "inserted_4" << endl;
    }

    cout<< "inserted_set.size() " <<  inserted_set.size() <<endl;
    for (auto my_class_ : inserted_set) {
        cout << "enum value: " << my_class_.source_type << endl;
    }
    cout<< "inserted_set.size() " <<  inserted_set.size() <<endl;
}
正如您所看到的,使用初始值设定项\u list初始化的集合行为不好(大小不同于迭代次数)。如果我以这种方式实施operator<:

bool my_class::operator<(const my_class& another) const
{
    return source_type<another.source_type;
}

~Marcin

在标准§25.4/2中规定:

比较是一种函数对象类型(20.9)。应用于Compare类型对象的函数调用操作的返回值,当上下文转换为bool(第4条)时,如果调用的第一个参数小于第二个参数,则返回true;否则返回false。Compare comp始终用于假设排序关系的算法。假设comp不会通过解引用迭代器应用任何非常量函数

(强调地雷)以及§25.4/3:

对于所有采用Compare的算法,有一个版本使用运算符<。也就是说,comp(*i,*j)!=false默认为*i<*j!=错对于25.4.3中描述的算法以外的算法,comp必须对值进行严格的弱排序

(强调矿山)如§25.4/4所述,这意味着:

术语“严格”指的是不可伸缩关系的要求(!comp(x,x)适用于所有x),术语“弱”指的是要求不如总排序的要求强,但比部分排序的要求强。如果我们把等价物(a,b)定义为!公司(a、b)和&!comp(b,a),那么要求comp和equiv都是传递关系:

  • comp(a,b)和comp(b,c)表示comp(a,c)
  • equiv(a,b)和&equiv(b,c)表示equiv(a,c)[注:在这些条件下,可以显示 那个
    • equiv是一种等价关系
    • comp在由equiv确定的等价类上导出一个定义良好的关系
    • 诱导关系是一个严格的全序关系

您正在违反这些要求,因此标准库正在违反其保证。

我相信
返回true肯定违反了严格弱排序的要求,因此我不希望它以合理的方式工作。我认为我的专业词汇太弱,无法理解我在比较中违反了哪个要求。请您用更容易理解的注释简短解释一下好吗?@MarcinKorn鉴于
Compare
对象的实现总是返回
true
,如果第一个参数不小于第二个参数,您就不会返回
false
。该部分已在第一个报价中为您突出显示。
bool my_class::operator<(const my_class& another) const
{
    return source_type<another.source_type;
}
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)