关于C++20容器命名要求的技术澄清问询
问题2:T不满足Destructible或EqualityComparable时,何时触发UB?
这两个要求的性质完全不同:
关于Destructible要求
C++20的Container通用要求明确规定,元素类型T必须满足Destructible(即可析构)。这是容器类型本身的必备条件,而非某个操作的前置条件:
- 只要你实例化一个容器模板(比如
std::vector<MyNonDestructableClass>),即使还没构造该容器的对象,已经违反了标准的命名要求,属于未定义行为。 - 实践中,编译器通常会在你尝试构造容器对象、调用
clear()/resize()等需要销毁元素的操作时报错,因为这些操作必然会调用T的析构函数——就像你的测试代码里,std::vector<MyNonDestructableClass>的构造会直接触发编译错误,因为MyNonDestructableClass的析构函数是被删除的。
关于EqualityComparable要求
如问题1所述,这只是特定操作的前置条件:
- 只要你不调用依赖相等比较的操作(比如容器的
operator==、std::count等),实例化并使用容器的其他功能(比如push_back、元素访问、迭代器遍历等)是完全符合标准的,不存在UB。 - 你的测试代码也验证了这一点:
vector<MyNonEqualityComparableClass>可以正常构造和使用,只有当你尝试执行u == v时,编译器才会报错——因为这个操作明确要求T支持operator==。
你的测试代码验证
以下是格式整理后的测试代码:
#include<vector> #include<iostream> // 移除==运算符的类 class MyNonEqualityComparableClass { template<typename T> auto operator==(T&& t) = delete; public: bool Mytestvalue = true; }; // 析构函数被删除的类 class MyNonDestructableClass { ~MyNonDestructableClass() = delete; }; // 空模板类 template<typename T> class MyTemplateClass {}; int main() { // 1. 不可析构类测试 { // 无法构造MyNonDestructableClass对象(析构函数不可访问) // MyNonDestructableClass a, b; // 可以实例化空模板类(未用到T的析构函数) MyTemplateClass<MyNonDestructableClass> mtc; // 无法构造vector<MyNonDestructableClass>(容器需要访问T的析构函数) // auto u = std::vector<MyNonDestructableClass>(); } // 2. 不可相等比较类测试 { MyNonEqualityComparableClass x, y; // 无法调用x == y(运算符被删除) // x == y; // 可以构造vector对象 auto u = std::vector<MyNonEqualityComparableClass>(); auto v = std::vector<MyNonEqualityComparableClass>(); u.push_back(x); v.push_back(y); x.Mytestvalue = !x.Mytestvalue; // 无法调用u == v(T不支持==) // u == v; std::cout << "The value of x.Mytestvalue is: \t" << std::boolalpha << x.Mytestvalue << std::endl; } }
输出结果:
The value of x.Mytestvalue is: false
这个结果完全符合标准的预期:
- 不可析构的
T无法用于容器,因为容器必须能够销毁元素; - 不可相等比较的
T可以用于容器,只要不触发需要相等比较的操作。
内容的提问来源于stack exchange,提问作者user2628206
相关产品推荐
相关产品推荐

