如何让 `std::basic_string<CustomClass>` 编译?
Posted
技术标签:
【中文标题】如何让 `std::basic_string<CustomClass>` 编译?【英文标题】:How to get `std::basic_string<CustomClass>` to compile? 【发布时间】:2012-09-05 21:48:47 【问题描述】:好的,我通常能够阅读、理解和修复编译器错误。但有了这个,我想我需要帮助。
我想要一个std::basic_string<CustomClass>
,其中CustomClass
是一个类。我不想为它编写自定义 char_traits 和分配器类,除非绝对必要(即,如果可能,我想使用 std::char_traits<CustomClass>
和 std::allocator<CustomClass>
)。
如果我在 CustomClass 中没有构造函数,它编译得很好。一加就报错:
调用'std::__1::basic_string<CustomClass, std::__1::char_traits<CustomClass>, std::__1::allocator<CustomClass> >::__rep'
的隐式删除默认构造函数
#include <iostream>
#include <string>
//#include <vector>
class CustomClass;
typedef std::basic_string<CustomClass> InstanceString;
typedef std::basic_string<int> IntString;
class CustomClass
public:
CustomClass()
: m_X()
CustomClass(const int x)
: m_X(x)
private:
int m_X;
;
int main(int argc, const char * argv[])
// This compiles fine
IntString s1(1, 2, 5);
// This would compile fine if there were no explicit constructors in Instance
//InstanceString s2e = InstanceString(Instance(), Instance(), Instance());
// This generates errors
InstanceString s2 = InstanceString(CustomClass(1), CustomClass(3), CustomClass(5));
std::cout << "Hello, World!\n";
return 0;
我知道这可能与隐式/显式构造函数、复制/移动语义和类似的东西有关。
我的问题是:
如何编译它(即我应该在类中添加什么构造函数/东西) 以及如何系统地找出如何修复这些类型的编译错误?【问题讨论】:
等等.. 为什么你甚至想要在basic_string
中的自定义类?哪些功能让您这样做?!
没有其他 STL 容器保证最后一个值初始化哨兵? ;)
Instance
必须是 POD 或标准布局(忘记哪个)。我认为关键部分是默认构造函数必须是=default
,以及复制构造函数和析构函数。
将substr
与复杂的字符类型一起使用(如果可能的话)会使效率低下的函数更加如此......
只需使用Boost.Range
,例如my_vec | boost::adaptors::sliced(first, last)
.
【参考方案1】:
从右边开始描述字符串库[strings.general]/1
的第一句:
本条款描述了用于操作任何非数组 POD 类型序列的组件。在本条款中,此类类型称为 char-like 类型,而 char-like 类型的对象称为 char-like 对象或简称为字符。
CustomClass
不是 char-like
类型,因为它不是 POD 类型,因此它不能存储在 basic_string
中。
libc++
实现无法编译,因为它使用了短字符串优化,并且这样做假定可以在联合中保存 CharT
数组而不提供自定义构造函数。
【讨论】:
感谢您提供具体信息。我感觉对于被认为是类似 char 的类型会有严格的限制,但你已经确认了。【参考方案2】:如你所说,错误信息显示
Call to implicitly-deleted default constructor of 'std::__1::basic_string, std::__1::allocator >::__rep'
我很确定__rep
是你的CustomClass
。它是说它正在尝试调用默认构造函数,但这已被隐式删除(通过您提供自己的构造函数)。我猜basic_string
使用std::is_default_constructible<>
。因此,您需要使用
CustomClass() = default;
正如 Mooing Duck 在 cmets 中所建议的那样。
它看起来很可能实际上使用了std::is_trivially_default_constructible<>
,这限制了你的类也必须是可简单构造的。
【讨论】:
我认为你是对的。我已经用CustomClass() = default;
替换了CustomClass() : m_X(x)
构造函数,它编译正常。但是现在当我尝试将其更改为具有 int 和 std::vectorstd::vector<>
,因为向量不是简单可构造的。您可能应该接受 Mankarse 的回答而不是我的回答,因为它解释了为什么事情是这样的,而我的回答只是解释了您班级的要求。
其实__rep在文件struct __rep union __long __l; __short __s; __raw __r; ; ;
。__short
包含CustomClass
。
我仍然需要弄清楚CustomClass() = default;
和CustomClass() : m_X()
之间的区别,只是为了提高我的错误理解能力。但首先我必须了解constructor = default
的含义...【参考方案3】:
简而言之,不能使用自定义的class
,因为短字符串优化可能会使用union
。
但是,您可以使用 enum
类型。
要正确完成这项工作需要做很多工作,而且您确实需要为您的类型实现std::char_traits
。
【讨论】:
以上是关于如何让 `std::basic_string<CustomClass>` 编译?的主要内容,如果未能解决你的问题,请参考以下文章
将 std::basic_string<Char> 转换为字符串
std::basic_string<TCHAR> 在 Windows 上会比 std::wstring 更可取吗?
错误 C3867 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>::c_s
传递给 std::basic_string 的分配器能否将其方法设为虚拟
VS错误C++:不存在从 "WCHAR [260]" 转换到 "std::basic_string<char," 的适当构造函数
no suitable ctr exists to convert from 'int' to 'std::basic_string<char,std::char_tra