如何让'std::basic_string<CustomClass>'编译?

How to get `std::basic_string<CustomClass>` to compile?

本文关键字:CustomClass lt gt 编译 string std basic      更新时间:2023-10-16

好吧,我通常很擅长阅读、理解和修复编译器错误。但是这次,我想我需要帮助。

我想要一个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;
    }

我知道这可能与隐式/显式构造函数、复制/移动语义等有关。

我的问题是:

  • 我该如何编译它(即,我应该向类中添加什么构造函数/东西)
  • 以及我如何系统地找出如何修复这些类型的编译错误

从右边开始字符串库[strings.general]/1:描述的第一句话

本条款描述了用于操作任何非数组POD类型的序列的组件。在这个子句中,这种类型被称为类字符类型,类字符类型的对象被称为类似字符的对象或简单的字符。

CustomClass不是char-like类型,因为它不是POD类型,因此它不能存储在basic_string中。

libc++实现无法编译,因为它使用了短字符串优化,并且在这样做的过程中,假设可以在不提供自定义构造函数的情况下将CharT的数组保持在并集中。

正如您所说,错误消息显示

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在评论中所建议的那样。

它似乎实际上使用了std::is_trivially_default_constructible<>,这也限制了类必须是可构造的。

简而言之,不能使用自定义class,因为短字符串优化可能使用union

但是,您可以使用enum类型。

这需要做大量的工作,并且您确实需要为您的类型实现std::char_traits