为什么`std::variant`的`operator=(&t)`的noexcept规范不随内部类型而变?

2026-04-16 18:573阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计771个文字,预计阅读时间需要4分钟。

为什么`std::variant`的`operator=(&t)`的noexcept规范不随内部类型而变?

:为什么std::variant的operator+(T t)的noexcept规范不依赖于内部类型的析构函数的noexcept规范?

内容:在cppreference上,可以看到如下模板类定义:

cpptemplate struct variant { variant(T t) noexcept(/* see below */)=default; variant(const variant&) noexcept(/* see below */)=default; variant(variant&&) noexcept(/* see below */)=default; variant& operator=(const variant&) noexcept(/* see below */)=default; variant& operator=(variant&&) noexcept(/* see below */)=default; template variant(variant v) noexcept(/* see below */)=default; template variant& operator=(variant&& v) noexcept(/* see below */)=default; operator T() const noexcept(/* see below */) &; operator T() const noexcept(/* see below */) const &; operator T() const noexcept(/* see below */) &&; operator T() const noexcept(/* see below */) const &&; T value() const noexcept(/* see below */) &; T value() const noexcept(/* see below */) const &; T value() const noexcept(/* see below */) &&; T value() const noexcept(/* see below */) const &&; operator bool() const noexcept(/* see below */) &; operator bool() const noexcept(/* see below */) const &; operator bool() const noexcept(/* see below */) &&; operator bool() const noexcept(/* see below */) const &&; template U value() const noexcept(/* see below */) &; template U value() const noexcept(/* see below */) const &; template U value() const noexcept(/* see below */) &&; template U value() const noexcept(/* see below */) const &&; template U& value() const noexcept(/* see below */) &; template U& value() const noexcept(/* see below */) const &; template U& value() const noexcept(/* see below */) &&; template U& value() const noexcept(/* see below */) const &&; void reset() noexcept(/* see below */) &; void reset() noexcept(/* see below */) const &; void reset(T t) noexcept(/* see below */) &; void reset(T t) noexcept(/* see below */) const &; void reset(variant t) noexcept(/* see below */) &; void reset(variant t) noexcept(/* see below */) const &; void reset(variant&& t) noexcept(/* see below */) &; void reset(variant&& t) noexcept(/* see below */) const &; void reset(variant& t) noexcept(/* see below */) &; void reset(variant& t) noexcept(/* see below */) const &; void reset(variant&& t) noexcept(/* see below */) &; void reset(variant&& t) noexcept(/* see below */) const &; template void reset(variant& t) noexcept(/* see below */) &; template void reset(variant& t) noexcept(/* see below */) const &; template void reset(variant&& t) noexcept(/* see below */) &; template void reset(variant&& t) noexcept(/* see below */) const &; template void reset(U t) noexcept(/* see below */) &; template void reset(U t) noexcept(/* see below */) const &; template void reset(variant& t) noexcept(/* see below */) &; template void reset(variant& t) noexcept(/* see below */) const &; template void reset(variant&& t) noexcept(/* see below */) &; template void reset(variant&& t) noexcept(/* see below */) const &; void swap(variant& other) noexcept(/* see below */) &; void swap(variant& other) noexcept(/* see below */) const &;};

其中,`operator+(T t)`的noexcept规范不依赖于内部类型的析构函数的noexcept规范。这是因为`operator+`操作符的noexcept规范只与操作符本身有关,而与内部类型的析构函数的noexcept规范无关。

长标题:为什么std:variant的operator =(T& t)的noexcept规范不依赖于内部类型的析构函数的noexcept规范?

我可以在cppreference上看到

template <class T> variant& operator=(T&& t) noexcept(/* see below */);

noexcept(std::is_nothrow_assignable_v<T_j&, T> && std::is_nothrow_constructible_v<T_j, T>)

所以这个编译:

struct FooThrow { ~FooThrow() noexcept(false) {throw;} }; static_assert(std::is_nothrow_assignable_v<std::variant<FooThrow, int>, int>);

但是它调用了FooThrow的析构函数,它是noexcept(false):

为什么`std::variant`的`operator=(&t)`的noexcept规范不随内部类型而变?

std::variant<FooThrow, int> x; x = 3; // throws

这似乎不对.我错过了什么吗?

通常,标准库类型不适用于具有抛出析构函数的类型.或者特别是,当析构函数实际发出异常时.关于它的一般规则( [res.on.functions])

In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C ++ standard library depends on components supplied by a C ++ program. If these components do not meet their requirements, this International Standard places no requirements on the implementation.

In particular, the effects are undefined in the following cases:

  • if any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.

由于variant :: operator =没有关于抛出析构函数的特殊声明,因此实际抛出这些析构函数是UB.

标签:OperatorU

本文共计771个文字,预计阅读时间需要4分钟。

为什么`std::variant`的`operator=(&t)`的noexcept规范不随内部类型而变?

:为什么std::variant的operator+(T t)的noexcept规范不依赖于内部类型的析构函数的noexcept规范?

内容:在cppreference上,可以看到如下模板类定义:

cpptemplate struct variant { variant(T t) noexcept(/* see below */)=default; variant(const variant&) noexcept(/* see below */)=default; variant(variant&&) noexcept(/* see below */)=default; variant& operator=(const variant&) noexcept(/* see below */)=default; variant& operator=(variant&&) noexcept(/* see below */)=default; template variant(variant v) noexcept(/* see below */)=default; template variant& operator=(variant&& v) noexcept(/* see below */)=default; operator T() const noexcept(/* see below */) &; operator T() const noexcept(/* see below */) const &; operator T() const noexcept(/* see below */) &&; operator T() const noexcept(/* see below */) const &&; T value() const noexcept(/* see below */) &; T value() const noexcept(/* see below */) const &; T value() const noexcept(/* see below */) &&; T value() const noexcept(/* see below */) const &&; operator bool() const noexcept(/* see below */) &; operator bool() const noexcept(/* see below */) const &; operator bool() const noexcept(/* see below */) &&; operator bool() const noexcept(/* see below */) const &&; template U value() const noexcept(/* see below */) &; template U value() const noexcept(/* see below */) const &; template U value() const noexcept(/* see below */) &&; template U value() const noexcept(/* see below */) const &&; template U& value() const noexcept(/* see below */) &; template U& value() const noexcept(/* see below */) const &; template U& value() const noexcept(/* see below */) &&; template U& value() const noexcept(/* see below */) const &&; void reset() noexcept(/* see below */) &; void reset() noexcept(/* see below */) const &; void reset(T t) noexcept(/* see below */) &; void reset(T t) noexcept(/* see below */) const &; void reset(variant t) noexcept(/* see below */) &; void reset(variant t) noexcept(/* see below */) const &; void reset(variant&& t) noexcept(/* see below */) &; void reset(variant&& t) noexcept(/* see below */) const &; void reset(variant& t) noexcept(/* see below */) &; void reset(variant& t) noexcept(/* see below */) const &; void reset(variant&& t) noexcept(/* see below */) &; void reset(variant&& t) noexcept(/* see below */) const &; template void reset(variant& t) noexcept(/* see below */) &; template void reset(variant& t) noexcept(/* see below */) const &; template void reset(variant&& t) noexcept(/* see below */) &; template void reset(variant&& t) noexcept(/* see below */) const &; template void reset(U t) noexcept(/* see below */) &; template void reset(U t) noexcept(/* see below */) const &; template void reset(variant& t) noexcept(/* see below */) &; template void reset(variant& t) noexcept(/* see below */) const &; template void reset(variant&& t) noexcept(/* see below */) &; template void reset(variant&& t) noexcept(/* see below */) const &; void swap(variant& other) noexcept(/* see below */) &; void swap(variant& other) noexcept(/* see below */) const &;};

其中,`operator+(T t)`的noexcept规范不依赖于内部类型的析构函数的noexcept规范。这是因为`operator+`操作符的noexcept规范只与操作符本身有关,而与内部类型的析构函数的noexcept规范无关。

长标题:为什么std:variant的operator =(T& t)的noexcept规范不依赖于内部类型的析构函数的noexcept规范?

我可以在cppreference上看到

template <class T> variant& operator=(T&& t) noexcept(/* see below */);

noexcept(std::is_nothrow_assignable_v<T_j&, T> && std::is_nothrow_constructible_v<T_j, T>)

所以这个编译:

struct FooThrow { ~FooThrow() noexcept(false) {throw;} }; static_assert(std::is_nothrow_assignable_v<std::variant<FooThrow, int>, int>);

但是它调用了FooThrow的析构函数,它是noexcept(false):

为什么`std::variant`的`operator=(&t)`的noexcept规范不随内部类型而变?

std::variant<FooThrow, int> x; x = 3; // throws

这似乎不对.我错过了什么吗?

通常,标准库类型不适用于具有抛出析构函数的类型.或者特别是,当析构函数实际发出异常时.关于它的一般规则( [res.on.functions])

In certain cases (replacement functions, handler functions, operations on types used to instantiate standard library template components), the C ++ standard library depends on components supplied by a C ++ program. If these components do not meet their requirements, this International Standard places no requirements on the implementation.

In particular, the effects are undefined in the following cases:

  • if any replacement function or handler function or destructor operation exits via an exception, unless specifically allowed in the applicable Required behavior: paragraph.

由于variant :: operator =没有关于抛出析构函数的特殊声明,因此实际抛出这些析构函数是UB.

标签:OperatorU