让我们采用以下函数声明:
void print(SomeType const* i);
Run Code Online (Sandbox Code Playgroud)
在这里,const*参数的性质i暗示了意图,即参数是optional,因为它可能是nullptr。如果这不是故意的,那么参数将只是一个const&. 交流可选的语义当然不是设计指针的初衷,但使用它们来这样做恰好在很长一段时间内都能正常工作。
现在,由于在现代 C++ 中通常不鼓励使用原始指针(并且应该避免使用std::unique_ptr并std::shared_ptr精确指示特定的所有权 -语义),我想知道如何正确指示函数参数的可选 -语义而不传递值,即复制,作为
void print(std::optional<SomeType> i);
Run Code Online (Sandbox Code Playgroud)
会做。
考虑了一段时间后,我想出了使用的想法:
void print(std::optional<SomeType const&> i);
Run Code Online (Sandbox Code Playgroud)
这实际上是最准确的。但事实证明std::optional 不能有引用类型。¹
另外,使用
void print(std::optional<SomeType> const& i);
Run Code Online (Sandbox Code Playgroud)
决不会是最优的,从那时起,我们将要求我们SomeType在向存在std::optional于主叫侧的,可能再次(或相当可能)需要复制那里。
问题:那么在不复制的情况下允许可选参数的现代方法是什么?在这里使用原始指针在现代 C++ 中仍然是一种合理的方法吗?
¹:具有讽刺意味的是,所描述的为什么std::optional不能有引用类型的原因(关于重新绑定或转发赋值的争议)不适用于const引用的std::optionals的情况,因为它们不能被分配。
在 C++ 协程中,等待者类型(即/的参数类型co_await和返回类型)需要、和三个方法。我知道在协程挂起/恢复的情况下调用1 的顺序。initial_suspendfinal_suspendawait_ready()await_suspend(std::coroutine_handle<...>)await_resume()
但我不清楚要求采用独特await_ready方法的理由是什么。当返回时true, 的调用await_suspend被阻止(并随之完全暂停)。然而,只需true从 中返回即可实现相同的效果await_suspend。
在这篇博客文章中,作者 David Mazi\xc3\xa8res 说
\n\n\n\n
await_ready是一种优化。如果返回true,则co_await不会暂停该函数。当然,您可以await_suspend通过恢复(或不挂起)当前协程来实现相同的效果,但在调用之前await_suspend,编译器必须将所有状态捆绑到协程句柄引用的堆对象中,这可能会很昂贵。
然而,对我来说,这似乎不是一个有效的论点:(可能是堆)分配的协程状态需要在promise_type::get_return_object()调用之前创建,并且总是被调用,因为promies_type-instance 是协程状态的一部分。因此,无论我们是否调用,句柄引用的协程状态都会被创建await_suspend。
回到将我的想法转化为代码的问题:我看不出在哪种情况下重写
\nstruct awaiter\n{\n bool await_ready() { /* <arbitrary-await-ready-body> */ }\n void /*| bool*/ await_suspend(std::coroutine_handle<...>) { /* <arbitrary-await-suspend-body> */ …Run Code Online (Sandbox Code Playgroud) 尽管阅读了一些 StackOverflow 帖子(this和this)和 cppreference 页面,但我无法弄清楚非静态局部变量与非静态局部变量 相比有何constexpr好处。 static constexpr
我能看到的唯一区别是每个调用都有自己的实例,但由于它是一个constexpr我在这里看不到实际优势(因为,如果我理解正确,这会导致每个实例都是相同且不可变的,使得多个实例只是多余的)。
或者,从另一个角度争论:由于非静态constexpr局部变量在(每次)函数调用时初始化,因此简单局部变量没有任何优势const,尽管它可以用于编译时评估。但是,当编译时评估需要它们时,没有必要将它们设置为非静态的。
所以我的问题是:我的论点有什么缺陷,在什么情况下非静态constexpr局部变量是合理的并且可能是最佳选择?
sizeof(double) char在寻找将s 组合到 a 的方法时double,我读了几篇文章,std::memcpy推荐使用以下方法:
char bytes[sizeof(double)];
// fill array
double d;
std::memcpy(&d, bytes, sizeof(double));
Run Code Online (Sandbox Code Playgroud)
但是,我想知道为什么进一步使用d可以定义行为。
如果它不是一个double,而是一个复杂的类对象,那么访问它肯定也不会被定义,不是吗?那么,为什么double.
编辑:为了使我的问题清楚,我想指定我的目标:我想找到一种方法将多个chars 组合成 adouble并进一步使用这个 double,而不会导致未定义的行为。我不double希望指定 的值。无论如何,我认为这是不可能的,因为标准甚至没有说明任何有关大小的信息,更不用说double. 但是,我要求d有一些有效的(即“可访问的”)double值。
我想知道std::enable_ifoverstatic_asserts防止模板实例化的优势。这个答案表明,这std::enable_if允许SFINAE,这在函数模板的情况下是一个令人信服的论点。
然而,这个论点对于类模板(和变量模板)是否合法?据我所知,那里不涉及重载决议,这使得 SFINAE - 再次,据我所知 - 不相关,但我可能是错的。如果是这样,你能举一个例子吗?
如果不是,我认为static_assert在类模板的情况下是给定问题(防止模板实例化)的更好解决方案,因为它可以说更明确、简洁和可读,并允许自定义错误消息。这是正确的还是我错过了 SFINAE 以外的一点?