C++ 如何从元组C++;

C++ 如何从元组C++;,c++,tuples,metaprogramming,C++,Tuples,Metaprogramming,一个过滤器如何从元组中复制类型 例如: using Tuple = std::tuple<int, double, int, double, std::string, std::string> using FilteredTuple = without_duplicates<Tuple>; { using not_unique = std::tuple<int, int, char, std::string, double, int>; using

一个过滤器如何从元组中复制类型

例如:

using Tuple = std::tuple<int, double, int, double, std::string, std::string>
using FilteredTuple = without_duplicates<Tuple>;
{
  using not_unique = std::tuple<int, int, char, std::string, double, int>;
  using filtered = boost::mp11::mp_unique<not_unique>;
  static_assert(std::is_same_v<std::tuple<int, char, std::string, double>, filtered>);
}
{
  using already_unique = std::tuple<int, char, std::string, double>;
  using filtered = boost::mp11::mp_unique<already_unique>;
  static_assert(std::is_same_v<std::tuple<int, char, std::string, double>, filtered>);
}
使用Tuple=std::Tuple
使用FilteredTuple=无重复项;
其中,以生成以下FilteredTuple类型的方式实现无_重复:

std::tuple<int, double, std::string>
std::tuple
这应该有效:

template <class Haystack, class Needle>
struct contains;

template <class Car, class... Cdr, class Needle>
struct contains<std::tuple<Car, Cdr...>, Needle> : contains<std::tuple<Cdr...>, Needle>
{};

template <class... Cdr, class Needle>
struct contains<std::tuple<Needle, Cdr...>, Needle> : std::true_type
{};

template <class Needle>
struct contains<std::tuple<>, Needle> : std::false_type
{};



template <class Out, class In>
struct filter;

template <class... Out, class InCar, class... InCdr>
struct filter<std::tuple<Out...>, std::tuple<InCar, InCdr...>>
{
  using type = typename std::conditional<
    contains<std::tuple<Out...>, InCar>::value
    , typename filter<std::tuple<Out...>, std::tuple<InCdr...>>::type
    , typename filter<std::tuple<Out..., InCar>, std::tuple<InCdr...>>::type
  >::type;
};

template <class Out>
struct filter<Out, std::tuple<>>
{
  using type = Out;
};


template <class T>
using without_duplicates = typename filter<std::tuple<>, T>::type;
模板
结构包含;
模板
结构包含:包含
{};
模板
结构包含:std::true\u类型
{};
模板
结构包含:std::false\u类型
{};
模板
结构过滤器;
模板
结构过滤器
{
使用type=typename std::conditional<
包含::值
,typename筛选器::类型
,typename筛选器::类型
>::类型;
};
模板
结构过滤器
{
使用类型=输出;
};
模板
使用无重复项=类型名筛选器::类型;


它通过迭代构造输出元组来工作。在添加每个类型之前,检查(使用谓词
contains
)它是否已经在输出元组中。如果没有,则添加它(std::conditional的“else”分支),否则不添加它(std::conditional的“then”分支)。

如果您有权访问Boost,则可以直接使用
Boost::mp11::mp_unique

例如:

using Tuple = std::tuple<int, double, int, double, std::string, std::string>
using FilteredTuple = without_duplicates<Tuple>;
{
  using not_unique = std::tuple<int, int, char, std::string, double, int>;
  using filtered = boost::mp11::mp_unique<not_unique>;
  static_assert(std::is_same_v<std::tuple<int, char, std::string, double>, filtered>);
}
{
  using already_unique = std::tuple<int, char, std::string, double>;
  using filtered = boost::mp11::mp_unique<already_unique>;
  static_assert(std::is_same_v<std::tuple<int, char, std::string, double>, filtered>);
}
{
使用not_unique=std::tuple;
使用filtered=boost::mp11::mp_unique;
静态断言(std::is_same_v);
}
{
使用已经_unique=std::tuple;
使用filtered=boost::mp11::mp_unique包含
#包括
模板
struct unique:std::type_identity{};
模板
结构唯一性
:std::conditional_t{};
模板
使用unique\u tuple=typename unique::type;

Piotr的代码非常简洁,应该优先使用。这里是一个扩展版本,用于在C++17上工作的通用可变模板类(例如
std::variant
或自定义容器):

#包括
//递归调用结束:元组使用`type`
模板
结构唯一性_impl{using type=T;};
//递归调用:1.使用第一类可变参数,
//如果不重复,则将其添加到元组中。
//2.用剩下的参数再次调用此函数
模板
结构唯一性\u impl
:std::conditional_t{};
//正向定义
模板
结构唯一元组;
//类专门化,以便可以从类型中提取元组参数
模板
struct unique_tuple:public unique_impl{};

如果你需要C++11,你只需要替换折叠表达式
(std::is|same|v | | |…)
来使用自制的
析取(请参见)。

我发现,对“If constexpr”语句进行推理通常比在头脑中解析std::conditional语句更容易

为此,我调整了Piotr的答案,使其符合该形式:

模板
constexpr自动生成唯一的元组(std::tuple)
{
如果constexpr((std::is_same_v| |…)
{
返回make_unique_tuple(std::tuple{});
}
其他的
{
如果constexpr(sizeof…(Rest)>0)
{
使用remaining=decltype(使数组唯一(std::tuple{});
返回std::tuple_cat(std::tuple{},剩余的{});
}
其他的
{
返回std::tuple{};
}
}
}

如果重复项不是连续的,您是否也需要过滤掉它们?例如,如果
没有重复项,您是否应该
std::tuple
,或者
std::tuple
?后者可能更容易实现。是的,我将更改示例以包括这一点problem@AndreasLoanjoe您不想解决的实际用例是什么这?对我来说听起来像是XY问题。我想从变量模板参数包中构造变量向量。但首先我需要确定没有重复的变量类型。上面的问题只是我正在努力解决的问题的最小示例。对于其他感兴趣的人,这里有一个测试链接:@AndreasLoanjoe乐于帮助,每隔一段时间就要面对这样的挑战,并使用我的Prolog/Lisp课程,这很有趣(因为逻辑/函数编程本质上就是模板元编程,尽管语法很奇怪)是的,我过去做过一些方案,但是语法对于C++中的操作仍然是令人眼花缭乱的,在这一点上,通过Outout参数是我的一个AHA时刻。在代码<实例> <代码>中延迟实例的实数化,以减少实例化的数量:(274行)与(782行)