Mak*_*rgy 10 c++ templates tuples template-meta-programming c++17
我需要一个constexpr
非常类似于的函数std::tuple_cat
,但是与其将所有元素合并为一个元组,而不必将所有元素合并到一个元组中,而是仅在尚未添加该类型的情况下,才需要添加该元素。
将谓词传递进来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);
Run Code Online (Sandbox Code Playgroud)
Evg*_*Evg 11
可能的解决方案:
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);
Run Code Online (Sandbox Code Playgroud)
通用化也适用于仅移动类型:
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)>>{});
}
Run Code Online (Sandbox Code Playgroud)
加法/更正。
我的初始测试表明它可以正常工作,但更深入的测试表明,使用会
std::forward_as_tuple
生成对临时变量(在中的“所有”变量make_tuple_unique
)的引用。我必须更改std::forward_as_tuple
to,std::make_tuple
并且一切都已修复。
没错:如果您传递右值作为参数,例如
make_tuple_unique(std::tuple<int>(1))
Run Code Online (Sandbox Code Playgroud)
返回类型为,std::tuple<int&&>
并且您会得到一个悬空的引用。但是用std::make_tuple
代替std::forward_as_tuple
make_tuple_unique(std::tuple<int&>(i))
Run Code Online (Sandbox Code Playgroud)
将具有type 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)));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
311 次 |
最近记录: |