关于容器命名要求的澄清

use*_*206 7 c++ std language-lawyer

我正在尝试了解容器类的 (C++20) 标准要求的具体细节,以期编写一些与标准库兼容的容器类。为了开始研究这个问题,我查找了命名需求的参考文献,特别是围绕容器需求的参考文献,并且只找到了一个称为标准给出的通用容器需求。Container阅读此要求后,我提出了两个疑问,我不确定并希望得到一些澄清:

  1. a == b两个容器类型的表达式的要求以元素类型是相等可比较的C为前提。T然而,稍后在同一页的“其他要求”标题下指出的是T始终相等可比较的明确要求。因此,根据我的阅读,上述要求的前提条件是多余的,无需给出。我的这种想法是否正确,还是还有其他我应该考虑的因素?

  2. 我很惊讶地看到明确的要求T:特别是上面的相等可比要求和指定的可破坏要求。这是否意味着构造不符合这些要求的类型的标准容器是未定义的行为,或者仅对它们执行某些标准库函数调用?

如果这两个问题听起来很愚蠢,我很抱歉,我目前正在尝试将我的 C++ 知识从对如何使用功能的基本了解转变为强大的理解,以便我可以编写良好的通用代码。虽然我试图使用该标准(的草案)来尽可能查找行为,但它的措辞通常过于冗长,让我无法完全理解实际所说的内容。


为了寻求答案,我编写了一个快速测试.cpp文件来尝试编译,如下所示。所有未注释的代码均使用设置为 C++20 的 MSVC 编译器进行编译。所有带注释的代码都不会编译,反之亦然,所有未注释的代码都会编译。似乎人们天真的认为应该起作用的东西尤其有效:

  • 尽管对象类型有效并且可以用于其他用途(例如作为模板参数!),但我们无法在没有析构函数的情况下构造任何对象。
  • 即使我们不尝试创建任何对象vector<T>T我们也无法创建没有析构函数的 对象T。大概是因为创建 的析构函数vector<T>尝试访问 的析构函数T
  • 我们可以创建一个没有运算符的类型的对象vector<T>,只要我们不尝试使用运算符,而这需要有运算符。TT====T==

然而,仅仅因为我的编译器允许我创建一个不相等可比较的对象vector<T>并不T意味着我已经实现了符合标准的行为/我们所有的行为都不是未定义的 - 这是我想要我关心的,特别是至少有一些违反了容器对象的通常要求。

代码:

#include<vector>
#include<iostream>

//A basic class with its == operator removed
class MyNonEqualityComparableClass
{
    //Destroy any possible == operator, for good measure
    template<typename T>
    auto operator==(T&& t) = delete;

    public:
        //Give the test struct a value so we mute the class and check
        bool Mytestvalue = true;
};

class MyNonDestructableClass
{
    ~MyNonDestructableClass() = delete;
};



// A basic class template with no functionality added
template<typename T>
class MyTemplateClass 
{};

int main()
{


//1. Non-destructable Class Test.
{
    
    //Compiler Grumbles if uncommented, no destructor is inaccessable for the class
    //MyNonDestructableClass a, b;

    //Class Dependent On my Nondestructable Class
    MyTemplateClass < MyNonDestructableClass> mtc;

    //Compiler Grumbles if uncommented, as class tries to acceess the inacessable destructor of MyNonDestructableClass
    //auto u = std::vector< MyNonDestructableClass>();

    
}

//2. Non-Equality-Comparable Class Test.
{
    
    MyNonEqualityComparableClass x, y;
    //Compiler Grumbles if uncommented 
    //x == y;

    //Compiler Fine with below
    auto u = std::vector<MyNonEqualityComparableClass>();
    auto v = std::vector<MyNonEqualityComparableClass>();
    u.push_back(x);
    v.push_back(y);
    x.Mytestvalue = !x.Mytestvalue;

    //Compiler Grumbles if uncommented 
    //u == v;

    std::cout << "The value of x.Mytestvalue is: \t" << std::boolalpha << x.Mytestvalue << std::endl;
}

}
Run Code Online (Sandbox Code Playgroud)

我的输出:

The value of x.Mytestvalue is:  false
Run Code Online (Sandbox Code Playgroud)

Mar*_*low 2

如果容器的成员是不可破坏的,那么容器除了添加新元素(或替换现有元素)之外永远不能做任何事情。eraseresize破坏都涉及破坏元素。如果您有一个T不可破坏的类型,并尝试实例化vector<T>(比如说),我预计它将无法编译。

至于重复的要求,我怀疑这只是 CppReference 人员编写该页面时潜入的内容。标准中的容器要求(在 的条目中a == b)提到元素必须是相等可比较的。