c++ - 如何就地构建可选聚合?
问题描述
如何就地构造可选聚合?看来我只能构造一个可选的单一事物,而不是可选的事物聚合。
#include <optional>
#include <iostream>
struct Unmovable
{
Unmovable(const Unmovable&) = delete;
Unmovable(Unmovable&&) = delete;
Unmovable& operator=(const Unmovable&) = delete;
Unmovable& operator=(Unmovable&&) = delete;
explicit Unmovable(const char* msg) {
std::cout << msg << '\n';
}
};
struct Things
{
Unmovable one;
Unmovable two;
};
int main(int argc, char* argv[]) {
const bool y = argc > 1 && argv[1][0] == 'y';
std::optional<Unmovable> optionalThing = y
? std::optional<Unmovable>{"works"}
: std::nullopt;
std::optional<Things> optionalThings = y
? std::optional<Things>{
#if ATTEMPT == 1
"jadda", "neida"
#elif ATTEMPT == 2
{"jadda", "neida"}
#elif ATTEMPT == 3
Things{"jadda", "neida"}
#elif ATTEMPT == 4
Unmovable{"jadda"}, Unmovable{"neida"}
#elif ATTEMPT == 5
{Unmovable{"jadda"}, Unmovable{"neida"}}
#elif ATTEMPT == 6
Things{Unmovable{"jadda"}, Unmovable{"neida"}}
#elif ATTEMPT == 7
std::in_place_t{}, "jadda", "neida"
#elif ATTEMPT == 8
std::in_place_t{}, {"jadda", "neida"}
#elif ATTEMPT == 9
std::in_place_t{}, Things{"jadda", "neida"}
#elif ATTEMPT == 10
std::in_place_t{}, Unmovable{"jadda"}, Unmovable{"neida"}
#elif ATTEMPT == 11
std::in_place_t{}, {Unmovable{"jadda"}, Unmovable{"neida"}}
#elif ATTEMPT == 12
std::in_place_t{}, Things{Unmovable{"jadda"}, Unmovable{"neida"}}
#endif
} : std::nullopt;
}
解决方案
如果你可以使用 C++20,那么你想要的是
std::optional<Things>{std::in_place, "jadda", "neida"};
正如在这个活生生的例子中看到的那样。你需要 C++20 的原因是std::in_place_t
构造函数使用的形式
T(std::forward<Args>(args)...)
初始化对象,但()
仅适用于具有构造函数的类,而Things
没有构造函数。C++ 已更新以解决此问题,并且该更改使其成为 C++20。
在 C++17 中,您可以通过提供用于Things
初始化成员的构造函数来使此代码工作。那看起来像
struct Things
{
Things(const char* msg1, const char* msg2) : one(msg1), two(msg2) {}
Unmovable one;
Unmovable two;
};
int main()
{
std::optional<Things>{std::in_place, "jadda", "neida"};
}
你可以看到在这个活生生的例子中工作
如果您好奇,可以在[dcl.init.general]/15.6.2.2中找到在 C++20 中添加的用于处理此问题的新语言
推荐阅读
- android - 处理 ViewModel 中的数据和 MVVM 中的 Fragment
- sql - 如果用户是管理员,则控制列的显示
- docker - Chromedriver 未在 docker 中启动
- mysql - 在 MySQL 中拆分逗号分隔值
- android - 无法从 Kotlin Android 中解析的 Json 数据中为 TextView 赋值
- r - 如何交换R中两列中的值?
- php - 使用 PHP 在 SQL Server 中下载二进制内容
- amazon-cloudwatch - 如何使用全局保留策略创建 CloudWatch LogGroup?
- c# - 如何制作一个用户必须输入完整选项的有效菜单?
- javascript - 在 promise catch 块内解析