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<bool>
时会出现奇怪的故障。特别是,它无法编译专业化的用法,因为它没有找到它的任何成员。对于其他类型——比如std::vector<char>
——完全没有问题。使用 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<bool>
的特化编码到主模板中(通常未定义);然后可以像往常一样完成其他类型的专业化,即使使用 bcc32,代码也可以按预期工作。
运行时断言可以验证特征模板的唯一非特殊化身是std::vector<bool>
的化身。然后,使用特征的模板会在方便的地方调用断言代码(也可以是静态函数)。
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<bool
,也许更简单的解决方法是not to use it at all,不是吗?
@Ami:我正在开发的代码的重点是面对vector<bool>
的性能(或缺乏性能)与vector<char>
的性能以及将原始内存视为打包位图,通过将这些类型特征化为具有不同特征的各种素筛实现。另一点是不仅要展示优化编译器(如 gcc 和 VC++)的行为,还展示非优化编译器(如 bcc32 和 bcc/clang)的行为。因此,vector<bool
和 bcc32 都保留在 in 中。
@DarthGizka:这是仅在classic 32bit compiler (bcc32) 中存在的问题,还是基于clang 的64bit (bcc64) 和new 32bit (bcc32c) 编译器也受到影响?
【参考方案1】:
std::
和 std::vector<bool>
中有一些可疑之处,因此您需要改用 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::_Bvector
或 std::allocator<bool>
而不是 std::vector<bool>
的技巧就像一个魅力(用 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>> 上均匀迭代