bcc32:专注于`std::vector<bool>`时出现奇怪的错误

Posted

技术标签:

【中文标题】bcc32:专注于`std::vector<bool>`时出现奇怪的错误【英文标题】:bcc32: strange error when specialising on `std::vector<bool>` 【发布时间】:2016-04-30 17:05:59 【问题描述】:

经典的 32 位 Borland/Embarcadero 编译器 - 又名 bcc32 - 当特性类专门用于 std::vector&lt;bool&gt; 时会出现奇怪的故障。特别是,它无法编译专业化的用法,因为它没有找到它的任何成员。对于其他类型——比如std::vector&lt;char&gt;——完全没有问题。使用 BC++ 5.5.1(免费)和 BC++ 7.1(RX/西雅图)进行测试。

有解决办法吗?

#include <iostream>
#include <typeinfo>
#include <vector>

template<typename T>
struct traits   ;

template<> struct traits< std::vector<char> >

   enum   ENUM = 42  ;

   static int func ()    return ENUM;  
;

template<> struct traits< std::vector<bool> >

   enum   ENUM = 666  ;

   static int func ()    return ENUM;  
;

///////////////////////////////////////////////////////////////////////////////////////////////////

template<typename T>
void test ()

   typedef traits<T> TT;

   // separate lines to see exactly where the compiler barfs
   std::cout << typeid(T).name();
   std::cout << " " << TT::ENUM;        // E2451 Undefined symbol 'ENUM'
   std::cout << " " << TT::func();      // E2451 Undefined symbol 'func'

   TT tt;
   std::cout << " " << tt.ENUM;         // E2316 'ENUM' is not a member of 'traits<std::_Bvector>'
   std::cout << " " << tt.func();       // E2316 'func' is not a member of 'traits<std::_Bvector>'
   std::cout << "\n";


int main ()

   test< std::vector<char> >();
   test< std::vector<bool> >();
   return 0;

注意:在某些情况下可能有用的有点hackish 解决方法是将vector&lt;bool&gt; 的特化编码到主模板中(通常未定义);然后可以像往常一样完成其他类型的专业化,即使使用 bcc32,代码也可以按预期工作。

运行时断言可以验证特征模板的唯一非特殊化身是std::vector&lt;bool&gt; 的化身。然后,使用特征的模板会在方便的地方调用断言代码(也可以是静态函数)。

template<typename T>
struct traits

   // specialisation for std::vector<bool> coded here...
   enum   ENUM = 666  ;

   static int func ()    return ENUM;  

   static void assert_only_vector_bool_not_specialised ()
   
      assert(typeid(T) == typeid(std::vector<bool>));
   
;

struct traits_specialisation_base

   static void assert_only_vector_bool_not_specialised ()
   
   
;

template<> struct traits< std::vector<char> >: traits_specialisation_base

   enum   ENUM = 42  ;

   static int func ()    return ENUM;  
;

// ...

template<typename T>
struct UsingTraits

   typedef traits<T> TT;

   UsingTraits ()
   
      TT::assert_only_vector_bool_not_specialised();
   
;

// ...

UsingTraits< std::vector<char> > erna;
UsingTraits< std::vector<bool> > fred;

【问题讨论】:

简单的解决方法是使用 1998 年C++ 标准化之后的编译器。 @Che:正如我帖子的第一段所述,bcc32 的 7.10 版 - 去年秋天与 RAD Studio RX/Seattle 一起发布的版本 - 有完全相同的问题作为旧版本。不,当使用 bcc32 时,不能选择使用符合标准的编译器。就是这样。 @Cheersandhth.-Alf 既然是vector&lt;bool,也许更简单的解决方法是not to use it at all,不是吗? @Ami:我正在开发的代码的重点是面对vector&lt;bool&gt; 的性能(或缺乏性能)与vector&lt;char&gt; 的性能以及将原始内存视为打包位图,通过将这些类型特征化为具有不同特征的各种素筛实现。另一点是不仅要展示优化编译器(如 gcc 和 VC++)的行为,还展示非优化编译器(如 bcc32 和 bcc/clang)的行为。因此,vector&lt;bool 和 bcc32 都保留在 in 中。 @DarthGizka:这是仅在classic 32bit compiler (bcc32) 中存在的问题,还是基于clang 的64bit (bcc64) 和new 32bit (bcc32c) 编译器也受到影响? 【参考方案1】:

std::std::vector&lt;bool&gt; 中有一些可疑之处,因此您需要改用 std:: 类型。只需更改为:

#include <iostream>
#include <typeinfo>
#include <vector>
//---------------------------------------------------------------------------
template<typename T> struct traits
    
    // this is safe constructor/destructor for Borland BDS2006 and later
    traits();
    traits(traits& a);
    ~traits();
    traits* operator = (const traits *a);
    //traits* operator = (const traits &a); // use this only if you have dynamic allocation members
    ;

template<> struct traits< std::vector<char> >
    
    enum   ENUM = 42  ;
    static int func ()    return ENUM;  
    ;

template<> struct traits< std::_Bvector >   // here use the std type directly
    
    enum   ENUM = 666  ;
    static int func ()    return ENUM;  
    ;
//---------------------------------------------------------------------------
template<typename T> void test ()
    
    typedef traits<T> TT;

    // separate lines to see exactly where the compiler barfs
    std::cout << typeid(T).name();
    std::cout << " " << TT::ENUM;        // E2451 Undefined symbol 'ENUM'
    std::cout << " " << TT::func();      // E2451 Undefined symbol 'func'

    TT tt;

    std::cout << " " << tt.ENUM;         // E2316 'ENUM' is not a member of 'traits<std::_Bvector>'
    std::cout << " " << tt.func();       // E2316 'func' is not a member of 'traits<std::_Bvector>'
    std::cout << "\n";

    // can ignore this ... it is just output to memo I do not use console
    AnsiString s="";
    s=s+typeid(T).name() + "\n";
    s=s+" " + AnsiString( TT::ENUM ) + "\r\n";        // E2451 Undefined symbol 'ENUM'
    s=s+" " + AnsiString( TT::func() ) + "\r\n";      // E2451 Undefined symbol 'func'
    s=s+" " + AnsiString( tt.ENUM ) + "\r\n";         // E2316 'ENUM' is not a member of 'traits<std::_Bvector>'
    s=s+" " + AnsiString( tt.func() ) + "\r\n";       // E2316 'func' is not a member of 'traits<std::_Bvector>'
    Form1->mm_log->Lines->Add(s);
    
//---------------------------------------------------------------------------
// this is your main()
__fastcall TForm1::TForm1(TComponent* Owner):TForm(Owner)
    
    test< std::vector<char> >();
    test< std::vector<bool> >();
    
//---------------------------------------------------------------------------

我使用 Windows 表单应用程序,所以忽略表单内容。构造函数/析构函数不是编译所必需的,但您应该添加它们,因为 Borland BDS2006 和后来的 C++ 引擎 错误。欲了解更多信息,请参阅:

BDS 2006 C hidden memory manager conflicts Too many initializers error for a simple array in bcc32

上面的代码给了我这个输出:

std::vector<char,std::allocator<char> >
 42
 42
 42
 42

std::vector<std::allocator<bool> >
 666
 666
 666
 666

【讨论】:

谢谢,专注于 std::_Bvectorstd::allocator&lt;bool&gt; 而不是 std::vector&lt;bool&gt; 的技巧就像一个魅力(用 bcc32 5.5.1 和 7.10 测试),它比我丑陋的要干净得多破解!并感谢您在链接文章中制定析构函数问题的详细信息和解决方案。赞一个! @DarthGizka 很高兴为您提供帮助

以上是关于bcc32:专注于`std::vector<bool>`时出现奇怪的错误的主要内容,如果未能解决你的问题,请参考以下文章

我不能将 lambda 作为 std::function 传递

如何在 C++17 中将 std::string 转换为 std::vector<std::byte>?

[swig-JavaScript] 是不是支持 std::vector<std::string>* 作为输出?

在 std::vector<T> 和 std::vector<unique_ptr<T>> 上均匀迭代

将函数返回从“std::vector<QString>”转换为“QVariant”

SWIG 如何正确包装 std::vector<double *>