C++20 标准草案的[basic.scope.pdecl]/1在注释中包含以下(非规范性)示例(合并拉取请求 3580之前的部分引用,请参阅此问题的答案):
unsigned char x = x;
Run Code Online (Sandbox Code Playgroud)
[...] x 用它自己的(不确定的)值初始化。
这实际上在 C++20 中有明确定义的行为吗?
通常T x = x;,由于x的值在初始化完成之前是不确定的,因此表单的自初始化具有未定义的行为。评估不确定的值通常会导致未定义的行为([basic.indent]/2),但在[basic.indent]/2.3中有一个特定的例外,它允许直接unsigned char从unsigned char具有不确定值的左值初始化变量(导致使用不确定值初始化)。
这本身并不会因此导致不确定的行为,但会为其他类型T不属于无符号窄字符类型或std::byte如int x = x;。这些注意事项也适用于 C++17 及之前的版本,另请参阅底部的链接问题。
然而,即使对于unsigned char x = x;,当前草案的[basic.lifetime]/7说:
类似地,在对象的生命周期开始之前 [...] 使用不依赖于其值的泛左值的属性是明确定义的。在以下情况下,程序具有未定义的行为:
泛左值用于访问对象,或
[...]
这似乎意味着x示例中的that值只能在其生命周期内使用。
[...]
类型 T 的对象的生命周期在以下情况下开始:
- [...] 和
- 它的初始化(如果有)完成(包括空初始化)([dcl.init]),
[...]
因此x的生命周期仅在初始化完成后才开始。但是在引用的例子中 …
我已经看到 IDE 中的默认标准通常不是最新发布的标准,甚至不是 IDE 中的最新标准。例如 JetBrains 的 Clion 有 C++20 和 C++17,但默认选项是 C++14。
是否有理由不使用最新发布的标准?
考虑这个代码:
struct A
{
template <typename T>
concept foo = true;
};
Run Code Online (Sandbox Code Playgroud)
它不编译。我的 Clang 10 给了我error: concept declarations may only appear in global or namespace scope,GCC 说了类似的话。
有理由不允许吗?我不明白为什么它不能工作,即使封闭类是一个模板。
我正在阅读Constraints上的cppreference页面并注意到这个例子:
// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t));
};
Run Code Online (Sandbox Code Playgroud)
我很困惑他们为什么要用std::forward.有些人试图在模板参数中支持引用类型吗?我们不想swap用forward左值调用,并且当标量(非参考)类型时T,表达式不是rvalues U吗?
例如,我希望这个程序在Swappable实现时失败:
#include <utility>
// example constraint from the standard library (ranges TS)
template <class T, class U = T>
concept bool Swappable = requires(T t, U u) {
swap(std::forward<T>(t), std::forward<U>(u));
swap(std::forward<U>(u), std::forward<T>(t)); …Run Code Online (Sandbox Code Playgroud) 考虑这个有效的 C++17 示例:
struct A {
bool operator==(const A&);
};
int main() {
return A{} == A{};
}
Run Code Online (Sandbox Code Playgroud)
当使用 -std=c++20 在 clang 中编译时,它给出:
struct A {
bool operator==(const A&);
};
int main() {
return A{} == A{};
}
Run Code Online (Sandbox Code Playgroud)
这个警告是否意味着 C++20 不允许使用典型的比较运算符来比较两个相同类型的对象?什么是正确的选择?这种情况在未来的选秀中会发生变化吗?
我有以下关于 C++20 中的 range 库的问题:
让std::ranges::contiguous_range<T>一个任意类型T.
我可以假设std::ranges::sized_range<T>吗?
#include <iostream>
int main(){
using type = int[2];
static_cast<type>(type{1,2}); //#1
}
Run Code Online (Sandbox Code Playgroud)
锵和GCC都抱怨这#1是形成不良的,并给予怪异的诊断。
Clang 报告
static_cast from 'int *' to 'type' (aka 'int [2]') is not allowed
Run Code Online (Sandbox Code Playgroud)
海湾合作委员会报告
invalid 'static_cast' from type 'type' {aka 'int [2]'} to type 'type' {aka 'int [2]'}
Run Code Online (Sandbox Code Playgroud)
但是,根据expr.static.cast#4
如果存在从 E 到 T的隐式转换序列([over.best.ics]),则表达式 E 可以显式转换为类型T
把一个类型转换成同一个类型不就叫恒等转换吗?
over.best.ics#general-8
如果不需要转换来将参数与参数类型匹配,则隐式转换序列是由身份转换 ([over.ics.scs]) 组成的标准转换序列。
我认为这里的一个关键规则是
转换序列是 [conv] 中定义的隐式转换,这意味着它受对象的初始化规则或单个表达式([dcl.init]、[dcl.init.ref])的引用的控制。
这意味着,假设一个结果对象将由t纯右值初始化。
static_cast from 'int *' to 'type' (aka 'int [2]') is not …Run Code Online (Sandbox Code Playgroud) 我在完全从任何模板中删除的上下文中玩弄 C++ 概念和函数重载,并偶然发现了这一点:
struct S
{
int mult(int x) requires (true) { return x; }
int mult(int x) requires (false) { return x * 2; }
};
int main()
{
std::cout << S{}.mult(5) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
g++ 11 拒绝编译此代码段,因为requires-clauses 可能不会附加到非模板函数。
然而,clang++ 13 对这个代码段很好,但令人惊讶的是它吐出10而不是5我所期望的。
我知道 C++20 标准最近才出炉,所以我完全理解关于概念有很多问题需要解决。
忽略常量字面概念的明显无用,我的问题是:带有 -requires子句的程序是否总是格式错误的false,可能不需要诊断?或者,也许,正如 g++ 所说,我什至根本没有合法的 C++?
我遇到过一些场景,我想说函数的返回值可能在函数体内,而不是调用它的 if 语句。
例如,假设我想将代码从使用LIKELY宏移植到使用新[[likely]]注释。但这些在句法上不同的地方:
#define LIKELY(...) __builtin_expect(!!(__VA_ARGS__),0)
if(LIKELY(x)) { ... }
Run Code Online (Sandbox Code Playgroud)
对比
if(x) [[likely]] { ... }
Run Code Online (Sandbox Code Playgroud)
没有简单的方法可以重新定义LIKELY宏以使用注释。会定义一个函数
inline bool likely(bool x) {
if(x) [[likely]] return true;
else return false;
}
Run Code Online (Sandbox Code Playgroud)
将提示传播到if?像
if(likely(x)) { ... }
Run Code Online (Sandbox Code Playgroud)
类似地,在通用代码中,很难在实际if语句中直接表达算法似然信息,即使该信息在其他地方是已知的。例如,a copy_ifwhere 谓词几乎总是假的。据我所知,没有办法用属性来表达,但如果分支权重信息可以通过函数传播,这是一个已解决的问题。
到目前为止,我还没有找到关于这个的文档,我不知道通过查看输出的程序集来测试这个的好设置。
背景
我有个任务类型既可以co_return和co_yield。在 LLVM 中,任务按预期工作并通过了一些早期测试。在 MSVC 和 GCC 中,代码以相同的方式失败(巧合?)。
简要问题
具有以下测试功能:
Task<int> test_yielding()
{
co_yield 1;
co_return 2;
}
Run Code Online (Sandbox Code Playgroud)
从 Task 对象中检索了两个值。
auto a = co_await fn;
auto b = co_await fn;
Run Code Online (Sandbox Code Playgroud)
a 的值预期为 1,b 的值预期为 2。
结果针对 进行测试a + b == 3。
上面的测试通过了,但是下面的测试失败了:
auto res = co_await fn + co_await fn
Run Code Online (Sandbox Code Playgroud)
GCC 和 MSVC 的 res 值为 4。两者都是从最终的 co_return 中检索到的。据我了解,第一次和第二次调用的co_await fn顺序应该是 1 和 2。
在 MSVC 和 GCC 中,代码失败,因为它们似乎重新排序await_resume,return_value …