如何原地构造可选聚合体?

8
如何就地构造可选的聚合?看起来我只能构造一个可选的单个元素,而不能构造一个可选的元素集合。
#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;
}

2
标准库类型通常使用()来初始化成员,因此不支持聚合初始化。在这里特别指出:https://eel.is/c++draft/optional#ctor-13 - dyp
因此,您可以通过为Things提供构造函数或使用将转发到{}样式初始化的包装器类型来解决此问题:https://compiler-explorer.com/z/P431GjaEv - dyp
请查看 emplace() 的文档。 - Sam Varshavchik
1
Things(char const* msg1, char const* msg2) : one{msg1}, two{msg2} {} std::make_optional<Things>("jadda", "neida") - Eljay
@SamVarshavchik emplace无法工作的原因与std::in_place_t构造函数重载不起作用的原因相同。 - rubenvb
1个回答

16
如果您可以使用C++20,那么您想要的是:
std::optional<Things>{std::in_place, "jadda", "neida"};

正如在这个实时示例中所看到的。你需要使用C++20的原因是std :: in_place_t构造函数采用以下形式。
T(std::forward<Args>(args)...)

Great! I am here to assist you. What language do you need me to translate from and to?
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"};
}

您可以在此实时示例中看到它的工作方式。


如果您感兴趣,新加入C++20以处理此问题的语言可以在[dcl.init.general]/15.6.2.2找到。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接