为什么 volatile int 可以转换为 int 而 volatile T 不能转换为 T?

Why is volatile int convertible to int but volatile T is not convertible to T?

考虑以下代码:

#include <iostream>
#include <type_traits>

struct type {};

int main(int argc, char* argv[]) {
    std::cout << std::is_convertible_v<volatile int, int> << " ";
    std::cout << std::is_convertible_v<volatile int, volatile int> << " ";
    std::cout << std::is_convertible_v<volatile type, type> << " ";
    std::cout << std::is_convertible_v<volatile type, volatile type> << std::endl;
    return 0;
}

打印出来

1 1 0 0

为什么volatile int可以转换为int,而volatile type不能转换为type?为什么 volatile type 甚至不能转换为 volatile type

有没有办法让 volatile class 可复制?

注意:欢迎参考 C++ 标准

此类转换为相同类型(忽略限定符)是复制/移动。

type 有一个隐式生成的复制和移动构造函数,它接受对非易失性限定对象的引用。此类引用不能绑定到 volatile 参数,因此不允许从 volatile 转换。

没有隐式生成的构造函数接受对 volatile 限定对象的引用。 (同样,没有隐式的 volatile 限定赋值运算符,也没有带有 volatile 限定参数的赋值运算符)。

这是 C++ 与允许复制可变结构的有效 C 不兼容的方式之一。

Is there a way to make a volatile class copyable?

您可以在技术上定义允许它的构造函数:

struct type {
    type()                       = default;
    type(type          const & ) = default;
    type(type                &&) = default;
    type(type volatile const & ) {}
    type(type volatile       &&) {}
};

根据您期望 volatile 的行为方式(对 volatile 对象的访问是实现定义的),可能不一定有一种方法可以按照您期望从 volatile 对象复制的方式来实现此构造函数,如果有几个子对象。

Volatile class 对象通常不是很有用,在我看来最好避免。

type 的隐式声明的默认构造函数具有此签名

type::type(type const&);

引用不能绑定到可变对象,因为那样会丢弃限定符。

[class.copy.ctor]

7 The implicitly-declared copy constructor for a class X will have the form

X::X(const X&)

if each potentially constructed subobject of a class type M (or array thereof) has a copy constructor whose first parameter is of type const M& or const volatile M&. Otherwise, the implicitly-declared copy constructor will have the form

X::X(X&)

无论哪种方式,编译器都不会隐式声明一个引用 volatile 对象的构造函数。

转换中的目标对象也是易变的这一事实没有区别。这样的转换需要一个能够绑定到可变源的复制构造函数。

构造函数不复制基本类型,因此此行为不限制它们。

Is there a way to make a volatile class copyable?

如果需要,您需要通过对 const volatile 对象的引用来接受用户声明的复制构造函数。