c++ - 为模板类专业化的构造函数/析构函数授予友谊 - 在 C++17 下工作,但在 C++20 下失败
问题描述
我发现了一种情况,代码在 C++17 下编译成功,但在 C++20 下编译失败。
这阻止了我们将现有的代码设计升级到更新的标准。
为什么这不能在 C++20 下编译?这似乎是对向后兼容性的奇怪破坏。
当我尝试将友谊授予模板类专业化的构造函数/析构函数时,会发生错误。
我正在使用带有 Ninja 的 MSVC 进行编译。
在 C++17 下编译成功。
在 C++20 下,我收到以下错误:
error C2838: '{ctor}': illegal qualified name in member declaration
error C2838: '{dtor}': illegal qualified name in member declaration
这是在 C++20 下导致错误的代码的简化复制,但在 C++17 下编译成功:
template<typename T, int V> class B {};
// specialization of class B
template<typename T> class B<T, 0> {
private:
T _t; // private data member
public:
constexpr inline B(T* p, int i) noexcept; // B constructor declaration
virtual inline ~B() noexcept; // B destructor declaration
};
// empty class with only private static data, no methods
class A {
private:
static int x; // private static variable
public:
// ERRORS HERE IN C++20, but compiles successfully in C++17
template<typename T> friend B<T, 0>::B(T*, int) noexcept; // C++20 ERROR
template<typename T> friend B<T, 0>::~B() noexcept; // C++20 ERROR
};
int A::x = 0; // global definition of private static variable
template<typename T> // B constructor definition
constexpr inline B<T, 0>::B(T* p, int i) noexcept : _t(0) { A::x++; }
template<typename T> // B destructor definition
inline B<T, 0>::~B() noexcept { A::x++; }
int main() {
A a;
B<const int, 0> b(0, 0);
}
B
我知道我可以通过为整个班级模板(包括所有专业)授予友谊来解决这个问题,但这是不可取的,因为我们希望将友谊限制在尽可能小的限制。
只有一两个模板专精(几十个)实际上需要这种友谊,如果没有必要,我们不想将友谊授予其他模板专精。
解决方案
Apple clang 12.0.0 即使在 C++17 中也不允许这样做(但显然它在 GCC 10 下编译):
[timr@Tims-Pro:~/src]$ g++ --std=c++17 -c x.cpp
x.cpp:19:42: warning: dependent nested name specifier 'B<T, 0>::' for friend class declaration is not supported; turning off
access control for 'A' [-Wunsupported-friend]
template<typename T> friend B<T, 0>::B(T*, int) noexcept; // C++20 ERROR
~~~~~~~~~^
x.cpp:20:42: error: expected the class name after '~' to name the enclosing class
template<typename T> friend B<T, 0>::~B() noexcept; // C++20 ERROR
^
推荐阅读
- javascript - Strophe Worker Websocket
- javascript - 离线保存数据
- .htaccess - 我想删除在自定义 php 博客 CMS 中动态添加的查询字符串
- javascript - 如何为 JSX 属性定义默认值以便 vscode 可以显示它们
- c# - Xamarin Forms:如何在 Android 中更改 Picker Controls 弹出窗口的背景颜色
- node.js - TLS 写入返回 400 Bad Request
- node.js - 使用 require('cors') 但仍然出现 CORS 错误
- twitter - 是否可以使用 Twitter API 来获取超过 7 天的回复?
- python - 如何从字符串中提取文本和表情符号?
- jquery - jquery更改在html选择选项中不起作用