I’ve been trying to upgrade (and slightly adapt) this solution from 2012 using modern features of C++.
My goal is actually slightly simpler than in that question; I’d like this:
triangularize_t<T0, T1, ..., TN-1, TN>
Run Code Online (Sandbox Code Playgroud)
To be equivalent to this:
std::tuple<
std::tuple<>,
std::tuple<T0>,
std::tuple<T0, T1>,
...
std::tuple<T0, T1, ..., TN-1>
>
Run Code Online (Sandbox Code Playgroud)
Such that std::tuple_element_t<N, result> has N elements. The type TN should not appear anywhere in the output.
Here’s what I’ve worked up to so far:
template <class _Tuple, class _Seq>
struct _tuple_head;
template <class _Tuple, size_t... _N>
struct _tuple_head<_Tuple, std::index_sequence<_N...>> {
using type = std::tuple<std::tuple_element_t<_N, _Tuple>...>;
};
template <class _Tuple, class _Seq>
struct _triangularize_impl;
template <class _Tuple, size_t... _N>
struct _triangularize_impl<_Tuple, std::index_sequence<_N...>> {
using type = std::tuple<typename _tuple_head<_Tuple, std::make_index_sequence<_N>>::type...>;
};
template <class... _Pack>
struct triangularize {
using type = _triangularize_impl<std::tuple<_Pack...>, std::index_sequence_for<_Pack...>>;
};
template <class... _Pack>
using triangularize_t = typename triangularize<_Pack...>::type;
Run Code Online (Sandbox Code Playgroud)
However, it doesn’t quite seem to be expanding the way I’d expect it to. Using triangularize_t<int, float> as a test, error messages seem to report that the output for std::get<0> and 1 return these types (identical for some reason).
_triangularize_impl<tuple<std::__1::tuple<int, float> >, __make_integer_seq<integer_sequence, unsigned long, 1UL> >
_triangularize_impl<tuple<std::__1::tuple<int, float> >, __make_integer_seq<integer_sequence, unsigned long, 1UL> >
Run Code Online (Sandbox Code Playgroud)
What have I missed here?
也许有人可以用更简单的方式做到这一点......但是如下呢?
template <typename T, std::size_t ... Is>
auto gtt_helper (std::index_sequence<Is...>)
-> std::tuple<std::tuple_element_t<Is, T>...>;
template <typename ... Ts, std::size_t ... Is>
auto getTriTuple (std::index_sequence<Is...>)
-> std::tuple<decltype(gtt_helper<std::tuple<Ts...>>
(std::make_index_sequence<Is>{}))...>;
template <typename ... Ts>
using triTuple
= decltype(getTriTuple<Ts...>(std::index_sequence_for<Ts...>{}));
Run Code Online (Sandbox Code Playgroud)
以下是完整编译C++14的例子
#include <type_traits>
#include <utility>
#include <tuple>
template <typename T, std::size_t ... Is>
auto gtt_helper (std::index_sequence<Is...>)
-> std::tuple<std::tuple_element_t<Is, T>...>;
template <typename ... Ts, std::size_t ... Is>
auto getTriTuple (std::index_sequence<Is...>)
-> std::tuple<decltype(gtt_helper<std::tuple<Ts...>>
(std::make_index_sequence<Is>{}))...>;
template <typename ... Ts>
using triTuple
= decltype(getTriTuple<Ts...>(std::index_sequence_for<Ts...>{}));
int main ()
{
using T0 = triTuple<char, int, long, long long>;
using T1 = std::tuple<std::tuple<>,
std::tuple<char>,
std::tuple<char, int>,
std::tuple<char, int, long>>;
static_assert( std::is_same<T0, T1>::value, "!" );
}
Run Code Online (Sandbox Code Playgroud)
为了回答你的问题(“我在这里错过了什么?”),你错过了 atypename和::typeatriangularize
在我看来,正确的版本应该是
template <class... _Pack>
struct triangularize {
// ..........VVVVVVVV add typename
using type = typename _triangularize_impl<std::tuple<_Pack...>,
std::index_sequence_for<_Pack...>>::type ;
// and add ::type ..........................................................^^^^^^
};
Run Code Online (Sandbox Code Playgroud)
不幸的是,您的(更正后的)代码似乎适用于 clang++ 但不适用于 g++;我怀疑有 g++ bug,但我不确定。
| 归档时间: |
|
| 查看次数: |
109 次 |
| 最近记录: |