包含自身映射的 C++ 变体

C++ variant containing a map of itself

我希望能够创建一个包含 std::map<std::string, MyVariant> 作为其案例之一的变体。理想的应该是可以写成

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

但这需要预先声明。

我知道之前有人问过类似的问题,例如 and ,但这些主要集中在 std::vector 的情况下,并且由于 C++17 std::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>;

不过,如果有其他方法,我也会感兴趣。

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

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

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