包含自身映射的 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::vector
、std::list
和 std::forward_list
。
如果你想使用 std::map
并且有标准的保证,你需要在某个时候添加一层间接。
我希望能够创建一个包含 std::map<std::string, MyVariant>
作为其案例之一的变体。理想的应该是可以写成
using MyVariant = std::variant<int, std::string, std::map<std::string, MyVariant>>;
但这需要预先声明。
我知道之前有人问过类似的问题,例如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::vector
、std::list
和 std::forward_list
。
如果你想使用 std::map
并且有标准的保证,你需要在某个时候添加一层间接。