标签: c++23

字节数组的放置新(隐式创建对象)是否会结束先前占用该存储的对象的生命周期?

P0593,在类型双关部分下,展示了这个例子:

float do_bad_things(int n) {
  alignof(int) alignof(float)
    char buffer[max(sizeof(int), sizeof(float))];
  *(int*)buffer = n;      // #1
  new (buffer) std::byte[sizeof(buffer)];
  return *(float*)buffer; // #2
}
Run Code Online (Sandbox Code Playgroud)

并指出:

提议的规则将允许一个int对象突然出现以使第 #1 行有效 [...],并且将允许一个float对象同样突然出现以使第 #2 行有效。

然而,这些示例在提议的规则下仍然没有定义行为。原因是 [basic.life]p4 的结果:

本文档中赋予对象和引用的属性仅在给定对象或引用的生命周期内适用。

具体来说,对象所持有的值仅在其整个生命周期内保持稳定。int当第 #1 行中的对象的生命周期结束时(当第 #2 行中的对象重用其存储时float),它的值就消失了。对称地,当创建 float 对象时,该对象具有不确定的值 ([dcl.init]p12),因此任何加载其值的尝试都会导致未定义的行为。

强调我的

该提案声称有问题的部分是float对象的(隐式)创建。但是上一行 ( new (buffer) std::byte[sizeof(buffer)]) 不是已经重用了存储(通过创建数组),结束了相关byte的生命周期吗?int据我了解,安置总是新的结束内存中创建新对象的对象的生命周期。

另外,这个评论说“新表达式不承诺保留存储中的字节。 ”这是否意味着new (buffer) std::byte[sizeof(buffer)]理论上可以改变 …

c++ lifetime placement-new language-lawyer c++23

6
推荐指数
1
解决办法
147
查看次数

就特定视图的使用而言,std::ranges::algorithm 与基于范围的 for() 循环相比在语义上有所不同

我想逐列查看 3x3 网格,所以我想我会std::views::stride像这样使用:

#include <array>
#include <iostream>
#include <ranges>

auto main() -> int {
    auto grid = std::array<std::array<int, 3>, 3>{{
            {1, 2, 3},
            {4, 5, 6},
            {7, 8, 9}
    }};

    namespace vs = std::views;

    auto strideCount = grid.size();
    auto allElements = grid | vs::join;

    auto columns = vs::iota(0uz, strideCount)
                   | vs::transform([allElements, strideCount](auto n) {
                        return allElements
                                | vs::drop(n)
                                | vs::stride(strideCount);
                   });

    for (auto&& column : columns) {
        for (auto element : column) {
            std::cout << element << ' …
Run Code Online (Sandbox Code Playgroud)

c++ for-loop std-ranges c++23

6
推荐指数
1
解决办法
301
查看次数

具有不完整类型的 lambda 函数

以下代码可以正常编译:

\n
#include <cstddef>\n\nstruct A {\n    char a;\n    static constexpr int off(void) { return offsetof(A, a); }\n    static constexpr int (*off_p)(void) = off;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

以下看似相似的代码\n仅使用 lambda 简称,但无法编译:

\n
#include <cstddef>\n\nstruct A {\n    char a;\n    static constexpr int (*off_p)(void) =\n         [](void) static constexpr ->int { return offsetof(A, a); };\n};\n
Run Code Online (Sandbox Code Playgroud)\n
$ g++ -std=c++23 bad.cpp \nIn file included from /usr/include/c++/13/cstddef:50,\n                 from bad.cpp:1:\nbad.cpp: In static member function \xe2\x80\x98A::<lambda()> static\xe2\x80\x99:\nbad.cpp:5:74: error: invalid use of incomplete type \xe2\x80\x98struct A\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n

所以基本上我有两个不同的问题,因为我不明白这里发生了什么。

\n
    \n
  1. 为什么在第一种情况下允许使用不完整类型?
  2. \n …

c++ c++23

6
推荐指数
1
解决办法
219
查看次数

如果 consteval 需要什么?

C++23 将引入if consteval. 这将在哪里使用,它与constexpr if?

c++ constexpr consteval c++23

5
推荐指数
1
解决办法
304
查看次数

约束自动投射有效吗?

从 C++20 开始,约束auto是通过以下方式引入的:

Concept auto identifier = init
Run Code Online (Sandbox Code Playgroud)

这意味着,例如:

std::integral auto x = 10;
Run Code Online (Sandbox Code Playgroud)

已验证。

此外,对于新表达式,概念可以与 配对auto

new Concept auto { expr };
// or:
new Concept auto ( expr );
Run Code Online (Sandbox Code Playgroud)

auto{expr}orauto(expr)在 C++23 中引入,大致相当于:

auto __temp { expr };
return __temp;
Run Code Online (Sandbox Code Playgroud)

这是否意味着Concept auto { expr }或者Concept auto ( expr )也有效?

这个简单的用例可用于尝试创建衰减副本,同时检查其按约束检查的操作。

c++ auto c++-concepts c++23

5
推荐指数
1
解决办法
317
查看次数

为什么 std::expected 中没有一元操作?

std::optional在 C++23 中,采用了一元运算 in ,后来又采用了std::expected. 为什么像and_then、、、这样的一元操作transform没有or_else包含在主论文中?

c++ c++23 std-expected

5
推荐指数
1
解决办法
1160
查看次数

为什么关联容器的擦除的异构版本需要转发引用?

erase关联容器中的异构版本(std::mapstd::unordered_map和)采用转发引用而所有其他异构函数(/ 、、)采用常量引用,std::multimap是否有任何特殊原因?std::unordered_multimapfindequal_rangecountcontains

例如在以下情况std::unordered_map

template<class K> iterator find(const K& k);
template<class K> const_iterator find(const K& k) const;
template<class K> size_type erase(K&& x);
Run Code Online (Sandbox Code Playgroud)

https://en.cppreference.com/w/cpp/container/unordered_map/erase(重载 4) https://en.cppreference.com/w/cpp/container/unordered_map/find(重载 3/4)

(最新工作草案) n4910第 24.5.4.1 节

(如上所述,这也适用于其他容器。)

c++ language-design c++23

5
推荐指数
1
解决办法
162
查看次数

为什么 C++23 Ranges::to 不将容器类型 C 限制为范围?

C++23 引入了非常强大的ranges::to从范围构造对象(通常是容器)的功能,具有以下定义([range.utility.conv.to]):

\n
template<class C, input_\xc2\xadrange R, class... Args> requires (!view<C>)\n  constexpr C to(R&& r, Args&&... args);\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,它仅限制模板参数C不是 a view,也就是说,C甚至可能不是 a range

\n

然而,它的实现用于range_value_t<C>获取 的元素类型C,这C至少使得模板参数必须对 a 进行建模的给range定约束。range_value_tRrange

\n

那么,为什么ranges::to对模板参数的约束如此宽松C

\n

我注意到论文的 R3 版本过去常常约束Cinput_range,这显然是合理的,因为input_range保证了 是range_value_t格式良好的,但在 R4 中这个约束被删除了。而且我没有找到任何关于此更改的评论。

\n

C那么,消除必须的约束有哪些考虑因素呢input_range

\n

有没有一个实际的例子来说明这种约束放松的好处?

\n

c++ range-v3 std-ranges c++23

5
推荐指数
1
解决办法
398
查看次数

是否在 c++23 中向 std::string 添加了接受 std::array&lt;char, N&gt; 的新构造函数?

最近在我们的代码中发现了一个错误,我们不小心将 a 转换std::array<char, N>std::string. 有缺陷的代码不会在 c++20 模式下编译,但会在 c++23 模式下编译并 //mostly// 工作,除了一些带有 null 终止的边缘情况。我正在使用海湾合作委员会11.1。

#include <iostream>
#include <string>
#include <array>

int main()
{
    std::array<char, 3> x = {'a', 'b', '\0'};
    std::string s(x);
    std::cout << "'" << s << "'" << " has length " << s.size() << std::endl;
    //outputs "'ab' has length 3"
}
Run Code Online (Sandbox Code Playgroud)

我怀疑这可能与P1989R2 - std::basic_string_view 的范围构造函数有关,但我不知道该怎么做。

这是一个错误还是只是一个奇怪的行为还是什么?

c++ c++23

5
推荐指数
1
解决办法
302
查看次数

在 C++ 中获取可以容纳给定量位的最小整数类型

如果我有编译时间常数,num_bits如何获得可以容纳这么多位的最小整数类型?

我当然可以这样做:

在线尝试一下!

#include <cstdint>
#include <type_traits>
std::size_t constexpr num_bits = 19;
using T =
    std::conditional_t<num_bits <=  8, uint8_t,
    std::conditional_t<num_bits <= 16, uint16_t,
    std::conditional_t<num_bits <= 32, uint32_t,
    std::conditional_t<num_bits <= 64, uint64_t,
        void>>>>;
Run Code Online (Sandbox Code Playgroud)

但也许标准库中存在一些现成的元函数来实现这个目标?

我创建这个问题只是为了专门从标准库中找出单个元函数。但是,如果除了我提出的上述解决方案之外,您还有其他好的建议如何解决此任务,那么也请发布此类解决方案......


更新。正如评论中所建议的,uint_leastX_t应该使用而不是uintX_t在上面的代码中的任何地方使用,因为uintX_t在某些平台上可能不存在,但uint_leastX_t始终存在。

c++ c++20 c++23

5
推荐指数
1
解决办法
890
查看次数