当显式默认析构函数时(例如:)struct s { ~s() = default; };,似乎该类型仍然可以在constexpr上下文中使用。但是,当显式删除析构函数(例如:)时struct s { ~s() = delete; };,Clang 不再认为该类型对于constexpr上下文是可行的。那么,正如标题所暗示的那样,具有显式删除的析构函数的类型仍然可以在上下文中使用吗constexpr?
struct a { ~a() = default; }; // all ok
struct b { ~b(){} }; // all fail
struct c { ~c() = delete; }; // fails on clang
struct d { constexpr ~d() = default; }; // all ok
struct e { constexpr ~e(){} }; // all ok
struct f { …Run Code Online (Sandbox Code Playgroud) 为什么 GCC version >=10.1会产生taking address of rvalue以下代码的错误?或者,当使用左值时,为什么它会抛出错误no matching function for call to 'a::n(a*)'?指针参数从哪里来?Clang 似乎完全可以接受代码(以及旧的 GCC 版本)。使用-std=c++14或-std=c++17进行编译会产生相同的行为。
示例代码:
struct a {
constexpr auto n() const { return 3; }
//
// static constexpr auto n() { return 3; } // ok
// auto n() const { return 3; } // ok
};
template<typename>
constexpr auto f() {
int{a{}.n()}; // error
//
int(a{}.n()); // ok
int x{a{}.n()}; // ok
} …Run Code Online (Sandbox Code Playgroud) 从 C++17 开始,现在有一种标准化的方法可以礼貌地建议编译器停止大喊大叫未使用的实体。当将此应用于变量、函数和 old-skool 类型别名时,我们必须使用以下形式的预期语法:
[[maybe_unused]] int x;
[[maybe_unused]] void f();
[[maybe_unused]] typedef void t;
Run Code Online (Sandbox Code Playgroud)
这里没什么奇怪的。然而,当将此属性说明符应用于结构、枚举,尤其是现代类型别名时,我们必须求助于各种官样文章才能使其发挥作用:
struct [[maybe_unused]] s;
union [[maybe_unused]] u;
enum class [[maybe_unused]] e;
using a [[maybe_unused]] = void; // what's up with this?
Run Code Online (Sandbox Code Playgroud)
[[maybe_unused]]类型别名的属性放置奇怪的原因是什么?难道真的就没有别的办法了吗?
根据 PEP8 风格指南,格式化类型别名 \xe2\x80\x94 的名称的正确方法是什么?
\n# mymodule.py\nfrom typing import TypeAlias\n\nmytype: TypeAlias = int\n\ndef f() -> mytype:\n return mytype()\n\ndef g() -> mytype:\n return mytype()\nRun Code Online (Sandbox Code Playgroud)\n应该mytype格式化,CapWords因为它引入了类似于创建新类的新类型?或者,应该mytype全部大写格式化,因为它的处理方式与常量类似?
有没有办法区分在程序的整个生命周期中保持不变(常量)的类型别名和可以更改的类型别名(类似于Final常量的注释)?
另外,应该mytype用下划线作为前缀(如_mytype)以指示类型别名不应在该模块之外使用?
c在尝试满足type 的概念时,Clang 和 GCC 之间似乎存在差异s。当不得不求助于 ADL 来寻找可行的 function 重载时f,Clang 似乎认为重载的自依赖性f(c auto)是一个硬错误。然而,GCC 似乎认为这是替换失败,只是丢弃候选而不是拒绝代码。
void f(int);
template<typename T>
concept c = requires(T t) { f(t); };
struct s {};
void f(s);
void f(c auto);
static_assert(c<s>); // clang nope, gcc ok, msvc nope
Run Code Online (Sandbox Code Playgroud)
这段代码是否应该被拒绝并导致硬错误?C++20 标准对这种情况有何规定?
铿锵错误消息:
<source>:4:13: error: satisfaction of constraint 'requires (T t) { f(t); }'
depends on itself
4 | concept c = requires(T t) { f(t); };
| ^~~~~~~~~~~~~~~~~~~~~~~
<source>:4:13: note: while …Run Code Online (Sandbox Code Playgroud) 与 GCC 12.2 和 MSVC 19.33 相比,以下代码示例不能使用 Clang 15 或 Clang trunk 进行编译。嵌套required子句中的约束表达式是否无效?
struct t {
constexpr auto b() const noexcept
{ return true; }
};
template<typename T>
concept c = requires(T t) {
requires t.b();
};
static_assert(c<t>);
Run Code Online (Sandbox Code Playgroud)
Clang 产生的错误消息:
<source>:11:1: error: static assertion failed
static_assert(c<t>);
^ ~~~~
<source>:11:15: note: because 't' does not satisfy 'c'
static_assert(c<t>);
^
<source>:8:14: note: because 't.b()' would be invalid: constraint variable 't'
cannot be used in an evaluated context
requires t.b();
^ …Run Code Online (Sandbox Code Playgroud) 考虑到以下代码示例,我希望必须template在此处使用关键字来指导编译器将变量视为v模板。然而,MSVC 拒绝使用该template关键字,而 Clang 和 GCC 实际上需要它。在这种情况下,C++20 标准中的哪条具体规则强制或禁止使用关键字template?
struct s {
template<typename...>
static constexpr auto v = true;
};
// all ok
static_assert([](auto x){ return decltype(x)::template v<>; }(s{}));
// clang ok, gcc ok, msvc nope
static_assert([](auto x){ return x.template v<>; }(s{}));
// clang nope, gcc nope, msvc ok
static_assert([](auto x){ return x.v<>; }(s{}));
Run Code Online (Sandbox Code Playgroud)
来自 Clang 的错误消息:
<source>:10:36: error: use 'template' keyword to treat 'v'
as a dependent template name
10 | static_assert([](auto …Run Code Online (Sandbox Code Playgroud) 关于 function f,模板化变量的非类型模板参数的替换约束表达式是b有效的常量表达式吗?C++20 标准的哪些特定措辞允许或禁止这种情况?
struct s { static constexpr bool v = true; };
template<auto> inline constexpr bool b = true;
constexpr bool f(auto x) requires b<x.v> { return true; }
static_assert(f(s{})); // clang ok, gcc nope, msvc ok
Run Code Online (Sandbox Code Playgroud)
来自 GCC 的错误消息:
<source>:3:36: error: missing template arguments before '<' token
3 | constexpr bool f(auto x) requires b<x.v> { return true; }
| ^
<source>:3:36: error: expected initializer before '<' token
<source>:4:15: error: 'f' was not …Run Code Online (Sandbox Code Playgroud) 关于C++17;GCC、Clang 和 MSVC 认为简单类类型不能由其任何数据成员类型构造。自 C++20 起,GCC 和 MSVC 改变了这一点,允许编译下面的示例。
#include <type_traits>
struct t {
int a;
};
static_assert(std::is_constructible<t, int>{});
Run Code Online (Sandbox Code Playgroud)
不幸的是,Clang 在编译时似乎不同意并拒绝这段代码-std=c++20。这是 Clang 的编译器错误吗?为什么所有编译器在编译时不t考虑可以使用 an 构造的类型?毕竟,这样似乎很容易构建。int-std=c++17t{0}
由于出现错误,以下代码示例似乎使用 GCC 12.2 进行编译,与 Clang 15 和 MSVC 19.33 不同illegal initializer type 'void'。我预计代码会被所有三个编译器拒绝,因为构造(临时)void 对象没有意义。
auto f() { return void{}; }
using t = decltype(f());
Run Code Online (Sandbox Code Playgroud)
在示例中,函数f仅与未计算的操作数一起使用。f是否允许这样使用,或者甚至应该拒绝它的定义?(我知道void()创建纯右值的法律表达式,但这不属于本文的重点。)
标准中看似相关的段落:
不完全定义的对象类型和 cv void 是不完整类型 ([basic.fundamental])。
不完全定义的对象类型的实例的大小和布局是未知的。