如何让`std :: basic_string <customclass>`编译?</customclass>

时间:2012-09-05 21:48:48

标签: c++ string c++11 std stdstring

好的,我通常能够阅读,理解和修复编译器错误。但有了这个,我想我需要帮助。

我希望std::basic_string<CustomClass> CustomClass是一个类。除非绝对必要,否则我不想为它编写自定义char_traits和allocator类(即如果可能,我想使用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;
    }

我理解这可能与隐式/显式构造函数,复制/移动语义以及类似的东西有关。

我的问题是:

  • 如何编译它(即我应该在类中添加什么构造函数/什么)
  • 以及如何系统地弄清楚如何修复这些类型的编译错误?

3 个答案:

答案 0 :(得分:4)

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

  

本条款描述了用于操纵任何非阵列POD类型的序列的组件。在本条款中,这些类型称为类似char的类型,类似char的类型的对象称为类似char的对象或简称为字符。

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

libc++实现无法编译,因为它使用短字符串优化,并且这样做假定可以在并集中保存CharT数组而不提供自定义构造函数。

答案 1 :(得分: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在评论中所说的那样。

它似乎实际上使用了std::is_trivially_default_constructible<>,它强加了你的类必须是可以轻易构造的限制。

答案 2 :(得分:2)

缺点是,您无法使用自定义class,因为短字符串优化可能会使用union

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

要做好相当多的工作,您需要为您的类型实施std::char_traits