2

我希望能够创建一个包含 astd::map<std::string, MyVariant>作为其案例之一的变体。理想的情况是能够写出类似的东西

using MyVariant = std::variant<int, std::string, std::map<std::string, MyVariant>>;

但这需要前向声明。

我知道之前已经问过类似的问题,例如herehere,但这些问题主要集中在 的情况下std::vector,并且由于 C++17std::vector允许使用不完整类型,而不允许使用std::map

特别是,我想知道这个答案中的定点组合器解决方案是否适用于这种情况?从该答案改编代码:

#include <map>
#include <string>
#include <variant>

// non-recursive definition
template<typename T>
using VariantImpl = std::variant<int, std::string, std::map<std::string, T>>;

// fixed-point combinator
template<template<typename> typename K>
struct FixCombinator : K<FixCombinator<K>>
{
    using K<FixCombinator>::K;
};

using MyVariant = FixCombinator<VariantImpl>;

但是,如果有另一种方法可以做到这一点,我也会对此感兴趣。

4

1 回答 1

3

这是不可能的(至少通过标准保证),因为std::variant要求使用的类型是完整的,并且std::map要求键和值类型在实例化时是完整的类型。但是只有在实例化之后,您的构造才会完成。

唯一允许这种递归构造(至少在某种程度上)的标准容器是std::vector,std::liststd::forward_list.

如果你想使用std::map它并且有标准的保证,你需要在某个时候添加一个间接级别。

于 2021-12-29T14:10:50.940 回答