std::tuple_cat 但只有独特的元素
std::tuple_cat but only with unique elements
我需要了一个与std::tuple_cat
非常相似的constexpr
函数,但是不是将所有元素合并到一个元组中,而是需要它仅在尚未添加该类型时才添加给定元素。
将谓词传递到std::tuple_cat
中会很好,但是不存在这样的API(这让我很伤心(。 我已经看到了几种使用类型特征查找合并类型的方法,这些类型特征我还没有完全理解,但没有以constexpr
函数的形式出现。 我不确定如何将它们放在一起,尽管我相信它可以做到。
像这样:
std::tuple<int, short, char> First;
std::tuple<short, float> Second;
std::tuple<int, double, short> Third;
std::tuple<int, short, char, float, double> Result = tuple_cat_unique(First,Second,Third);
可能的解决方案:
template<std::size_t i, class Tuple, std::size_t... is>
constexpr auto element_as_tuple(const Tuple& tuple, std::index_sequence<is...>)
{
if constexpr (!(std::is_same_v<std::tuple_element_t<i, Tuple>,
std::tuple_element_t<is, Tuple>> || ...))
return std::make_tuple(std::get<i>(tuple));
else
return std::make_tuple();
}
template<class Tuple, std::size_t... is>
constexpr auto make_tuple_unique(const Tuple& tuple, std::index_sequence<is...>)
{
return std::tuple_cat(element_as_tuple<is>(tuple,
std::make_index_sequence<is>{})...);
}
template<class... Tuples>
constexpr auto make_tuple_unique(const Tuples&... tuples)
{
auto all = std::tuple_cat(tuples...);
constexpr auto size = std::tuple_size_v<decltype(all)>;
return make_tuple_unique(all, std::make_index_sequence<size>{});
}
constexpr std::tuple<int, short, char> first(1, 2, 3);
constexpr std::tuple<short, float> second(4, 5);
constexpr std::tuple<int, double, short> third(6, 7, 8);
constexpr auto t = make_tuple_unique(first, second, third);
static_assert(std::get<0>(t) == 1);
static_assert(std::get<1>(t) == 2);
static_assert(std::get<2>(t) == 3);
static_assert(std::get<3>(t) == 5);
static_assert(std::get<4>(t) == 7);
也适用于仅可移动类型的泛化:
template<std::size_t i, class Tuple, std::size_t... is>
constexpr auto element_as_tuple(Tuple&& tuple, std::index_sequence<is...>)
{
using T = std::remove_reference_t<Tuple>;
if constexpr (!(std::is_same_v<std::tuple_element_t<i, T>,
std::tuple_element_t<is, T>> || ...))
// see below
// return std::forward_as_tuple(std::get<i>(std::forward<Tuple>(tuple)));
return std::tuple<std::tuple_element_t<i, T>>(
std::get<i>(std::forward<Tuple>(tuple)));
else
return std::make_tuple();
}
template<class Tuple, std::size_t... is>
constexpr auto make_tuple_unique(Tuple&& tuple, std::index_sequence<is...>)
{
return std::tuple_cat(element_as_tuple<is>(std::forward<Tuple>(tuple),
std::make_index_sequence<is>())...);
}
template<class... Tuples>
constexpr auto make_tuple_unique(Tuples&&... tuples)
{
auto all = std::tuple_cat(std::forward<Tuples>(tuples)...);
return make_tuple_unique(std::move(all),
std::make_index_sequence<std::tuple_size_v<decltype(all)>>{});
}
添加/更正。
我最初的测试表明它工作正常,但更深入的测试表明,使用
std::forward_as_tuple
会生成对临时变量(make_tuple_unique
中的"all"变量(的引用。我不得不将std::forward_as_tuple
更改为std::make_tuple
,一切都已修复。
这是正确的:如果你传递一个右值作为参数,比如
make_tuple_unique(std::tuple<int>(1))
返回类型为 std::tuple<int&&>
,您将获得一个悬而未决的引用。但用std::make_tuple
而不是std::forward_as_tuple
make_tuple_unique(std::tuple<int&>(i))
将具有类型 std::tuple<int>
,并且引用将丢失。有了std::make_tuple
,我们失去了左值,有了std::forward_as_tuple
,我们就失去了普通的价值。要保留原始类型,我们应该
return std::tuple<std::tuple_element_t<i, T>>(
std::get<i>(std::forward<Tuple>(tuple)));
相关文章:
- std::tuple默认构造函数,带有move可构造元素
- 如何在std :: tuple中的每个元素上应用constexpr函数
- 使用派生自 'std::tuple' 的元素在 'std::tuple' 上调用 'std::get' - 格式不正确
- std::tuple的实现是否允许在触发空类元素的派生到基转换时失败
- std::map<tuple<int,int>.lower_bound/upper_bound 前缀搜索,而不找到后缀的最小/最大元素
- 在运行时按索引访问 std::tuple 元素的最佳方法
- 以后可以使用分配器构造 std::tuple 的元素吗?
- 如何创建具有指定数量的元素(相同类型)的 boost::tuple
- void * 到 std::tuple 在运行时的第 n 个元素
- 将std::pair转换为具有任意数量元素的std::tuple
- 以自然(非反向)顺序将func应用于std::tuple中的元素
- 为什么 libstdc++ 以相反的顺序存储 std::tuple 元素
- 如何在编译时不知道时从 std::tuple 获取第 i 个元素?
- 访问boost::fusion::tuple中的第0个元素
- 如何通过索引设置std::tuple元素
- 对于boost::hana::tuple,元素访问的时间复杂度是多少?
- 如何获取对 std::tuple 元素的引用
- 无法使用 boost::bind 来访问 boost::tuple 元素
- 为什么我不能使用 std::find 当容器中的基本元素是 boost::tuple 时
- 如何向Boost.Tuple中添加元素