我已经阅读了最新的草案,其中lazy_split_view添加了内容。
但后来我发现它split_view改名为lazy_split_view,而且又split_view更新了。
libstdc++最近还通过使用GCC Trunk版本https://godbolt.org/z/9qG5T9n5h实现了这一点
我这里有一个简单的天真的程序,它显示了两个视图的用法,但我看不到它们的区别:
#include <iostream>
#include <ranges>
int main(){
std::string str { "one two three four" };
for (auto word : str | std::views::split(' ')) {
for (char ch : word)
std::cout << ch;
std::cout << '.';
}
std::cout << '\n';
for (auto word : str | std::views::lazy_split(' ')) {
for (char ch : word)
std::cout << ch;
std::cout << '.';
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
one.two.three..four.
one.two.three..four. …Run Code Online (Sandbox Code Playgroud) C++23 可能会通过标头引入堆栈跟踪机制<stacktrace>。
我知道我们将会有一个由“ies”std::stack_trace组成的班级std::stacktrace_entry,这一切都很好。但是 - 仅现有的这不会有太大帮助,因为每个人都必须煞费苦心地确保他们始终收集堆栈跟踪并将其放入他们抛出的异常中。这是不好的。
相反,我想要的是每个(?)异常自动携带堆栈跟踪,这样当我检查它或打印它时,甚至当它在未捕获时自动打印时,堆栈跟踪都会被打印出来。
这是计划中可能实现的,还是我要求太多?
C++23 草案要求结构或类的后续非静态数据成员必须具有更高的地址。据我所知,早期的标准也部分地要求这样做,但是当允许编译器重新排序这些数据成员时有一些规则。这里有人能告诉我哪些规则在什么时候适用吗?
自从std::generator正在进入 CPP23,我正在尝试 MSVC 的不完整版本。
然而,我注意到,yield与 一起使用时,它似乎恰好丢失了一个std::views::take。这是示例:
#include <iostream>
#include <ranges>
#include <experimental/generator>
std::experimental::generator<int> GeneratorFn(void) noexcept
{
co_yield 1;
co_yield 2;
co_yield 3;
co_yield 4;
co_yield 5;
co_yield 6;
co_yield 7;
co_yield 8;
co_yield 9;
co_return;
}
int main(int argc, char** args) noexcept
{
auto Ret = GeneratorFn();
for (auto&& i : Ret | std::views::take(2))
std::cout << i << '\n';
for (auto&& i : Ret | std::views::take(3))
std::cout << i << '\n';
for (auto&& i …Run Code Online (Sandbox Code Playgroud) 有一个相当典型的任务是同时对两个数组进行排序,假设数组的相同索引元素形成虚拟对,并对其进行排序。这样的问题至少在 10 年前就出现过:boost zip_iterator 和 std::sort
现在这个任务可以使用range-v3库来解决:
#include <array>
#include <range/v3/all.hpp>
int main() {
auto x = std::array{ 3, 2, 4, 1 };
auto y = std::array{'A', 'B', 'C', 'D'};
ranges::sort( ranges::views::zip( x, y ) );
// here x = {1,2,3,4}, y={'D','B','A','C'}
}
Run Code Online (Sandbox Code Playgroud)
在线演示: https: //gcc.godbolt.org/z/WGo4vGsx5
在 C++23 中出现了std::ranges::zip_view,我的期望是可以仅使用标准库编写相同的程序:
#include <array>
#include <ranges>
#include <algorithm>
int main() {
auto x = std::array{ 3, 2, 4, 1 };
auto y = std::array{'A', 'B', 'C', 'D'};
std::ranges::sort( std::views::zip( …Run Code Online (Sandbox Code Playgroud) 我目前正在使用 C++ 模块,尝试对我们公司的代码 C++ 基础进行现代化改造,以使用模块来实现核心功能。特别是即将推出的 C++23std模块,作为预编译头的更好替代品,它看起来非常有趣。
所以我使用的是Visual Studio 2022 17.5 Preview 2.0,它对模块有初步支持std。顺便说一句,我遇到了编译器内部错误,我向Microsoft报告了这个错误。
在我们所有的 C++ 源文件中,现在都有一个import std;语句,而且效果很好。每个应该位于std命名空间中的标识符似乎都按预期导出。我测量到与之前使用预编译头相比,编译时间略有减少。
我发现,如果你,你在任何标准import std;C++ 头文件中都会遇到很多奇怪的编译错误,因为 Microsoft 编译器会感到困惑并抱怨重新定义。所以我小心翼翼地将它们全部删除。 #include <>
我的问题是,标准库中定义了一些宏(主要是在 C 兼容库中),这些宏显然没有导出,因为 C++ 模块在设计上从不导出宏。
我们的代码库使用的标准宏数量非常有限,但我认为很难避免它们。以下是它们的简短列表(不确定是否完整):
stdouterrnova_start, va_arg,va_end对于va_*宏,我#include <stdarg.h>和它在 VS 2022 上编译得很好,尽管它打破了我之前提到的规则。这可能是因为该标头几乎只有宏。但对于stdout和errno,我不知道该怎么办。
C++23 是否指定在导入模块时如何访问重要的标准宏,例如stdout或?有没有好的解决方法?errnostd
让我描述一个场景,首先我们有一个函数,它返回一些我们无法确定其有效性的数据,即
auto random_predicate() -> bool
{
int v = uniform_dist(e1); // uniform distribution 1 to 100
return (v % 5);
}
Run Code Online (Sandbox Code Playgroud)
其中uniform_dist()是适当种子的均匀分布,我们有一个enum class将用于错误处理的,即
enum class Error
{
ValueError
};
Run Code Online (Sandbox Code Playgroud)
然后我们执行某种基于视图的处理,该处理random_predicate()在操作中使用,如下所示:
std::vector<int> vs{1,2,3,4,5};
auto result = vs
| views::filter([](int i){ return i % 2; })
| views::transform([](int i) -> std::expected<int, Error> {
auto v = random_predicate();
if (v) return std::unexpected<Error>(Error::ValueError);
else return i * i;
});
Run Code Online (Sandbox Code Playgroud)
因此,在该操作结束时,我们可以断言
static_assert(
std::is_same_v<
std::decay_t<std::ranges::range_value_t<result>>,
std::expected<int, Error>
>
)
Run Code Online (Sandbox Code Playgroud)
事实上将会是真的。 …
因此,我决定使用mdspan普通跨度 + 元素访问函数的组合,而不是简单的组合。但是 - 我想对 mdspan 做的一件明显的事情是迭代它的元素。这就是我用一维跨度来实现的方法:
std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto sp = std::span(vec.data(), 12);
for (auto x : sp) {
std::cout << x << ' ';
}
std::cout << '\n';
Run Code Online (Sandbox Code Playgroud)
...但不适用于mdspan's (使用Kokkos 实现):
std::vector vec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto ms = std::mdspan(vec.data(), 12);
for (auto x : …Run Code Online (Sandbox Code Playgroud) c++23operator ()引入了和的静态版本operator []:
#include <iostream>\n#include <format>\n\nstruct S\n{\n static int operator()(int a, int b) { return a + b; }\n static int operator[](int a, int b) { return a - b; }\n};\n\nint main()\n{\n std::print("({})[{}]", S{}(1, 0), S{}[3, 1]); // (1)[2]\n// ^^ ^^ <-- Create temporary instances of \'S\'?!\n std::print("({})[{}]", S()(2, 1), S()[5, 1]); // (3)[4]\n// ^^ ^^ <-- Create temporary instances of \'S\'?!\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n令我震惊的是,为了调用静态版本的运算符()和[]需要类的实例;我期望能够从类型中调用两个运算符(作为其他静态成员),但它的格式不正确:
// type …Run Code Online (Sandbox Code Playgroud) 在 C++ 23 之前,当使用std::cout将输出发送到时stdout,以下两种在打印字符串末尾添加新行的方法之间存在区别:
std::cout << "Hello World\n";std::cout << "Hello World" << std::endl;其中第二个通常更可取,因为它会导致输出流刷新,而不是需要调用std::cout.flush().
在 C++ 23 中,现在有两个新的打印函数以及标准库的新组件。我们有std::print和std::println。
在刷新输出流时,这些函数是否有区别?
或者,刷新输出流是否不再是这些新实现中相关的概念?
文档中cppreference没有提到冲洗:
c++ ×10
c++23 ×10
std-ranges ×3
c++-modules ×1
c++20 ×1
fmt ×1
generator ×1
iteration ×1
mdspan ×1
ranged-loops ×1
stack-trace ×1
stl ×1