标签: c++23

为什么 C++23 std::move_only_function 没有推导指南?

C++23 引入了std::function的表兄弟std::move_only_function,就像它的名字一样,它是仅移动可调用对象的仅移动包装器(演示):

#include <functional>
#include <memory>

int main() {
  auto l = [p = std::make_unique<int>(0)] { };
  std::function<void(void)>           f1{std::move(l)}; // ill-formed
  std::move_only_function<void(void)> f2{std::move(l)}; // well-formed
}
Run Code Online (Sandbox Code Playgroud)

但与 不同的是std::function,该标准没有为其定义推导指南(演示):

#include <functional>

int func(double) { return 0; }
int main() {
  std::function f1{func};           // guide deduces function<int(double)>
  std::move_only_function f2{func}; // deduction failed
}
Run Code Online (Sandbox Code Playgroud)

禁止 CTAD 有理由吗?

c++ std-function c++17 c++23

13
推荐指数
1
解决办法
2328
查看次数

使用 using 定义命名空间中的类

[class.pre] p3状态:

如果类头名称包含嵌套名称说明符,则该类说明符不应位于类范围内。 如果其类名是标识符,则类说明符应对应于嵌套名称说明符所引用的类、类模板或命名空间中可命名的一个或多个声明;它们都应具有相同的目标范围,并且类说明符的目标范围的目标范围就是该范围。

[例子:

namespace N {
  template<class>
  struct A {
    struct B;
  };
}
using N::A;
template<class T> struct A<T>::B {};    // OK
template<> struct A<void> {};           // OK
Run Code Online (Sandbox Code Playgroud)

--结束示例]

第一句话和例子似乎有所不同。

包含嵌套名称说明符(但仅“依赖”使用A<void>)的模板的专业化是否仍然符合?

clang 和 msvc 接受它,gcc 显示错误

错误:在其命名空间之外显式特化“模板结构 N::A”必须使用嵌套名称说明符 [-fpermissive]

附加背景

介绍原始措辞和示例注释的论文是P1787R6:声明以及在哪里找到它们,包含以下行:

template<> struct A<void> {};         // error: A not nominable in …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer c++23

11
推荐指数
0
解决办法
486
查看次数

为什么“zip_view”不支持“output_range”?

我注意到 C++23zip_view有以下限制:

template<input_range... Views>
  requires (view<Views> && ...) && (sizeof...(Views) > 0)
class zip_view;
Run Code Online (Sandbox Code Playgroud)

这意味着只能zip_view压缩输入范围。

我想知道为什么它排除output_range,因为output_range在我看来支持可能很有用。例如,我可以压缩一堆output_ranges 来同时写入,如下场景:

/* zipped input_range */
auto zip_in = views::zip(views::iota(0, 3),
                         views::iota(3, 6),
                         views::iota(6, 9));

std::vector<int> v1, v2, v3;
auto make_insert_range = [](auto inserter) {
  return ranges::subrange(inserter, std::unreachable_sentinel);
};
/* zipped output_range */
auto zip_out = views::zip(make_insert_range(std::back_inserter(v1)),
                          make_insert_range(std::back_inserter(v2)),
                          make_insert_range(std::back_inserter(v3)));

/* copy */
ranges::copy(zip_in, zip_out.begin());
std::println("v1: {}", v1); // v1: [0, 1, 2]
std::println("v2: {}", …
Run Code Online (Sandbox Code Playgroud)

c++ std-ranges c++23

11
推荐指数
0
解决办法
232
查看次数

为什么 C++23 范围适配器要求可调用对象是可复制构造的?

一些范围适配器,例如filter_\xc2\xadview,take_\xc2\xadwhile_\xc2\xadviewtransform_view使用std::optional\ 的同类copyable-box来存储可调用对象:

\n
template<input_\xc2\xadrange V, copy_\xc2\xadconstructible F>\nclass transform_view : public view_interface<transform_view<V, F>> {\n private:\n  V base_ = V();\n  copyable-box<F> fun_;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

这要求可调用对象Fcopy_\xc2\xadconstructible,这也阻止我们将捕获仅移动对象的可调用对象传递给transform_viewGodbolt):

\n
#include <ranges>\n#include <memory>\n\nstruct MoveOnlyFun {\n  std::unique_ptr<int> x;\n  MoveOnlyFun(int x) : x(std::make_unique<int>(x)) { } \n  int operator()(int y) const { return *x + y; }\n};\n\nint main() {\n  auto r = std::views::iota(0, 5)\n         | std::views::transform(MoveOnlyFun(1));\n}\n
Run Code Online (Sandbox Code Playgroud)\n

既然view不是必需的copy_constructible,为什么我们要求可调用的呢 …

c++ c++20 std-ranges c++23

10
推荐指数
1
解决办法
617
查看次数

C++23 标准中的 bfloat16_t 是什么?

Cppreference文档包含 5个stdfloat新类型:float16_tfloat32_tfloat64_tfloat128_tbfloat16_t虽然前 4 种类型是不言自明的(分别是 16、32、64 和 128 位的浮点数),但最后一种类型bfloat16_t对我来说根本不清楚。这个类型代表什么?它的名字中的是什么b意思?

c++ floating-point c++23

9
推荐指数
1
解决办法
2055
查看次数

无法从initializer_list移动​​的解决方法?

方便的initializer_list语法似乎是以无法移动列表成员、创建不必要的副本为代价的。

struct  A
{
    // some members which are dynamic resources...
    A() { cout << "Default Constructor\n"; }
    A(const A& original) { cout << "Copy constructor\n"; }
    A(A&& original) { cout << "Move constructor\n";  }
};
    
int main() {
    vector<A> v1{ A() , A() }; // calls copy
    vector<A> v2;
    v2.push_back(A()); v2.push_back(A()); // calls move
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,这是因为取消引用初始化器迭代器会给出const T,即使尝试移动时也会复制它。

有解决方法吗?

阅读/sf/answers/3101541901/,提出了一种使用可变参数模板的解决方案,如下所示:

template<class Array> struct maker;

// a maker which makes a std::vector
template<class …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list move-semantics c++20 c++23

9
推荐指数
1
解决办法
306
查看次数

O(1) 在 std::ranges::views::iota 中查找/包含

我知道 iota 可能很复杂(例如无限),因此在一般情况下这不容易完成,但在某些情况下应该可以在 O(1) 中进行查找/包含操作。

例如

int main() {
    auto vals = views::iota(10'000'000'000, 100'000'000'000);
    return ranges::find(vals, 74'656'000'000) != vals.end();
}
Run Code Online (Sandbox Code Playgroud)

“无限”运行(进行线性搜索)

显然检查可以在 O(1) 内完成。

有没有办法用 C++ 来实现这种通用方式(即在其他视图上查找/包含需要线性时间,并且当它检测到 iota 时需要 O(1)),或者我需要手动检测传递给我的函数的视图是什么时候有限iota视图并进行>=front <=back检查?

c++ c++20 std-ranges c++23

9
推荐指数
1
解决办法
515
查看次数

为什么 C++23 stacktrace_entry 与 source_location 不同?

class stacktrace_entry {
public:
  string description() const;
  string source_file() const;
  uint_least32_t source_line() const;
  /* ... */
};
Run Code Online (Sandbox Code Playgroud)
struct source_location {
  // source location field access
  constexpr uint_least32_t line() const noexcept;
  constexpr uint_least32_t column() const noexcept;
  constexpr const char* file_name() const noexcept;
  constexpr const char* function_name() const noexcept;
  /* ... */
};
Run Code Online (Sandbox Code Playgroud)

它们的目的基本相同,为什么它们有差异,特别是 中没有列stacktrace_entry,或者甚至不共享同一类?

c++ stack-trace c++23

8
推荐指数
1
解决办法
534
查看次数

如何在不编写标识样板的情况下访问 C++23 std::Optional 中包含的值?

我正在使用 C++23std::optional添加,但我不知道如何优雅地访问对象的值(如果optional处于活动状态)。

我知道我可以使用if,但这就是C ++20 。

我真的很喜欢 C++23 API 的变化,但我不知道如何跳过实现身份的样板。例如:

#include <functional>
#include <iostream>
#include <optional>

void print(std::optional<std::string>& name) {
    name.transform([](std::string& x) {
        std::cout << x << std::endl;
        // I just want to print, without modifying optional, but next line is required
        return x;
    });
}

int main() {
    std::optional<std::string> name{{"Bjarne"}};
    print(name);
}
Run Code Online (Sandbox Code Playgroud)

感觉就像std::optional缺少invoke会员功能一样。

注意:在我的示例中,我在转换后不会链接任何其他内容,但为了简洁起见,我关心可选内容是否被修改。

c++ stdoptional c++23

8
推荐指数
1
解决办法
1502
查看次数

鉴于 C++23 对 constexpr 的放宽,constexpr 不能成为默认值吗?

关键字constexpr在引入 C++11 标准时对其函数实施了相当严格的限制。C++14 和 C++20 放宽了这些限制(最值得注意):

  • C++14 允许多个return语句static_assert等。
  • C++20 允许try并且asm

C++23 进一步软化了这些限制。从我在cppreference中看到的,constexprfor函数似乎只剩下以下含义:

  • 它不能是协程
  • 对于构造函数和析构函数,该类必须没有虚拟基类
  • 对于 constexpr 函数模板和类模板的 constexpr 成员函数,至少一种特化必须满足上述要求。

C++23 甚至删除了 constexpr 函数必须在编译时对于p2448r2中的任何类型“可计算”的限制。根据我的理解,这完全消除了constexpr在编译时评估函数的想法。

是这样吗?如果是这样,constexpr函数还有什么用处呢?

c++ language-design constexpr constexpr-function c++23

8
推荐指数
1
解决办法
1100
查看次数