gpt4 book ai didi

c++ - 从给定的嵌套 boost-variant 类型创建一个新的 boost-variant 类型

转载 作者:可可西里 更新时间:2023-11-01 18:35:31 26 4
gpt4 key购买 nike

假设我有一个嵌套的 boost::variant -类型TNested包含一些类型和一些其他 boost::variant类型(它本身不能再次包含 boost::variant types ,因此不会有递归)。

我正在寻找模板别名 flatten<TNested>这将评估为 boost::variant类型没有嵌套 boost::variant s,例如TFlatten ,而可能的重复类型正在被删除,例如int只出现一次。

我真的不知道这是否能以某种方式实现。

#include <boost/variant.hpp>
#include <boost/any.hpp>
#include <iostream>

struct Person;

typedef boost::variant<int, double, boost::variant<std::string, int>, boost::variant<Person>> TNested;
typedef boost::variant<int, double, std::string, Person> TFlatten;

template<typename NestedVariant>
using flatten = //???

int main() {
flatten<TNested> x;
std::cout << typeid(x) == typeid(TFlatten) << std::endl;
}

最佳答案

wandbox example

这是一个有效的基于 C++11 递归模板的解决方案,适用于您的示例:

using nested = variant<int, double, variant<std::string, int>, variant<Person>>;
using flattened = variant<int, double, std::string, int, Person>;

static_assert(std::is_same<flatten_variant_t<nested>, flattened>{}, "");

总体思路:

std::tuple用作通用类型列表和 std::tuple_cat用于连接类型列表。

A flatten_variant<TResult, Ts...>定义了递归元函数,它执行以下操作:

  • TResult将填充扁平化类型,并在递归结束时返回。

    • Ts... 时递归结束是空的。
  • 非变体类型附加到 TResult .

  • 变体类型被解包,它们所有的内部类型被递归地扁平化,然后附加到 TResult .


实现:

namespace impl
{
// Type of the concatenation of all 'Ts...' tuples.
template <typename... Ts>
using cat = decltype(std::tuple_cat(std::declval<Ts>()...));

template <typename TResult, typename... Ts>
struct flatten_variant;

// Base case: no more types to process.
template <typename TResult>
struct flatten_variant<TResult>
{
using type = TResult;
};

// Case: T is not a variant.
// Return concatenation of previously processed types,
// T, and the flattened remaining types.
template <typename TResult, typename T, typename... TOther>
struct flatten_variant<TResult, T, TOther...>
{
using type = cat<TResult, std::tuple<T>,
typename flatten_variant<TResult, TOther...>::type>;
};

// Case: T is a variant.
// Return concatenation of previously processed types,
// the types inside the variant, and the flattened remaining types.
// The types inside the variant are recursively flattened in a new
// flatten_variant instantiation.
template <typename TResult, typename... Ts, typename... TOther>
struct flatten_variant<TResult, variant<Ts...>, TOther...>
{
using type =
cat<TResult, typename flatten_variant<std::tuple<>, Ts...>::type,
typename flatten_variant<TResult, TOther...>::type>;
};

template<typename T>
struct to_variant;

template<typename... Ts>
struct to_variant<std::tuple<Ts...>>
{
using type = variant<Ts...>;
};
}

template <typename T>
using flatten_variant_t =
typename impl::to_variant<
typename impl::flatten_variant<std::tuple<>, T>::type
>::type;

关于c++ - 从给定的嵌套 boost-variant 类型创建一个新的 boost-variant 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39272268/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com