2015-08-27 19 views
1

這是我的代碼看起來像std :: set <my_class>的Initializer_list初始化用平凡的運算符<。 gcc + /標準庫中的錯誤?

#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; 
} 

這是輸出:

bracers_initialized_set.size() 4 
enum value: 2 
enum value: 1 
bracers_initialized_set.size() 4 
inserted_1 
inserted_2 
inserted_3 
inserted_4 
inserted_set.size() 4 
enum value: 4 
enum value: 3 
enum value: 2 
enum value: 1 
inserted_set.size() 4 

正如你可以看到initializer_list初始化設定的行爲不好(大小比迭代的次數不同)。如果我實現運營商<這樣:

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

則輸出是這兩個例子是正確的。

但是,無論操作符<的外觀如何,initializer_list初始化和插入輸出都不應該相同?還不應該大小總是反映元素的數量?

$ GCC -v

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) 

〜馬爾欽

+0

我相信'返回true;'在一個謂詞中肯定違反了嚴格的弱排序的要求,所以我不會期望它以一種合理的方式工作 –

回答

3

在它的指定的是,在§25.4/ 2標準:

比較是一個功能對象類型(20.9)。當上下文轉換爲bool(條款4)時,應用於Compare類型對象的函數調用操作的返回值在調用的第一個參數小於第二個參數時返回true,否則返回false。假設一個排序關係,比較comp被用於整個算法。假定comp不會通過解除引用的迭代器應用任何非常量函數。

(重點煤礦),而且在§25.4/ 3:

對於採用比較所有的算法,存在使用運營商<,而不是一個版本。也就是說,comp(* i,* j)!= false默認爲* i < * j!= false。 對於除了25.4.3中描述的算法以外的其他算法正常工作,comp必須對值產生嚴格的弱排序。

(重點煤礦),這意味着,如在§25.4/ 4描述:

術語嚴格指漫反射的關係的要求(!排版(X,X)對於所有x) ,而對於需求來說這個術語的弱點不如總體排序的那些強,但比部分排序的要強。如果我們將equiv(a,b)定義爲!comp(a,b)& &!排版(B,A),則要求是排版和當量兩者可傳遞關係:

  • 排版(A,B)& &排版(B,C)意味着排版(A,C)
  • 當量(A,b)& &當量(b,C)意味着當量(A,C)。[注:在這些條件下,可以示出 該
    • 當量是一個等價關係
    • 排版誘導關於等價類det的明確定義的關係ermined由equiv
    • 誘導關係是嚴格的總排序。 - 注完]

您正在打破這些要求,所以標準庫是打破了保證。

+0

我認爲我的專業詞彙量太弱,無法理解它要求即時通訊與我的比較。你能否簡單解釋一下容易理解的評論? –

+0

@MarcinKorn假設你的'Compare'對象的實現總是返回'true',那麼在第一個參數不小於第二個參數的情況下,你不會返回'false'。該部分在第一次報價中突出顯示。 – Shoe

相關問題