std::type_pack_element

878 views
Skip to first unread message

Andrey Davydov

unread,
Oct 11, 2018, 3:05:37 PM10/11/18
to ISO C++ Standard - Future Proposals
It's often needed to index into template parameter pack, when working with variadic templates, for instance in implementation of std::get<size_t> of tuple and variant. I wonder if there is any proposal to add metafunction 
<std::size_t I, typename ...Ts>
using type_pack_element = ...
It can be implemented using existing language facilities or, similarly to std::make_integer_sequence, using compiler intrinsic. It's already implemented in Clang (__type_pack_element), and IMO it should not be hard to support in other compilers. Moreover it should be much more efficient from compile-time perspective because variadic pack is stored in some vector-like data structure, and consequently to get element by index from it is much cheaper than class template instantiation, overload resolution, etc...

Tony V E

unread,
Oct 11, 2018, 3:30:15 PM10/11/18
to ISO C++ Standard - Future Proposals
Can you show an example of use?

Sent from my BlackBerry portable Babbage Device
From: Andrey Davydov
Sent: Thursday, October 11, 2018 3:05 PM
To: ISO C++ Standard - Future Proposals
Subject: [std-proposals] std::type_pack_element

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/f2d44cc1-d626-4adb-9f4c-b4555ee4cb08%40isocpp.org.

Barry Revzin

unread,
Oct 11, 2018, 3:32:40 PM10/11/18
to ISO C++ Standard - Future Proposals

What you're looking for is called mp_at_c in the proposal, except it takes a "list" as the first parameter instead of a trailing template parameter. So yours implemented in terms of that one would just be:

template <size_t I, typename... Ts>
using type_pack_element = mp_at_c<mp_list<Ts...>, I>;

This is already in Boost as the Mp11 library, if you want to just use it. 

Jonathan Müller

unread,
Oct 11, 2018, 3:36:23 PM10/11/18
to std-pr...@isocpp.org
On Thu, Oct 11, 2018, 21:30 Tony V E <tvan...@gmail.com> wrote:
Can you show an example of use?

Sent from my BlackBerry portable Babbage Device
From: Andrey Davydov
Sent: Thursday, October 11, 2018 3:05 PM
To: ISO C++ Standard - Future Proposals
Subject: [std-proposals] std::type_pack_element

It's often needed to index into template parameter pack, when working with variadic templates, for instance in implementation of std::get<size_t> of tuple and variant. I wonder if there is any proposal to add metafunction 
<std::size_t I, typename ...Ts>
using type_pack_element = ...
It can be implemented using existing language facilities or, similarly to std::make_integer_sequence, using compiler intrinsic. It's already implemented in Clang (__type_pack_element), and IMO it should not be hard to support in other compilers. Moreover it should be much more efficient from compile-time perspective because variadic pack is stored in some vector-like data structure, and consequently to get element by index from it is much cheaper than class template instantiation, overload resolution, etc...

template <size_t I, typename ... Ts>
struct tuple_element<I, tuple<Ts...>>
{
     using type = type_pack_element<I, Ts...>;
};

Andrey Davydov

unread,
Oct 11, 2018, 3:52:23 PM10/11/18
to ISO C++ Standard - Future Proposals
template<typename... Ts, size_t... J>
class tuple_impl<index_sequence<J...>, Ts...> : element_storage<Ts, J>...
{
 
template<size_t I> friend decltype(auto) get(tuple & t)
 
{
   
using element_type = type_pack_element<I, Ts...>;
   
return static_cast<element_storage<element_type, I> &>(t).get();
 
}
};

Andrey Davydov

unread,
Oct 11, 2018, 4:01:34 PM10/11/18
to ISO C++ Standard - Future Proposals
On Thursday, October 11, 2018 at 2:05:37 PM UTC-5, Andrey Davydov wrote:
It's often needed to index into template parameter pack, when working with variadic templates, for instance in implementation of std::get<size_t> of tuple and variant. I wonder if there is any proposal to add metafunction 
<std::size_t I, typename ...Ts>
using type_pack_element = ...
It can be implemented using existing language facilities or, similarly to std::make_integer_sequence, using compiler intrinsic. It's already implemented in Clang (__type_pack_element), and IMO it should not be hard to support in other compilers. Moreover it should be much more efficient from compile-time perspective because variadic pack is stored in some vector-like data structure, and consequently to get element by index from it is much cheaper than class template instantiation, overload resolution, etc...

Thank you for the link to this proposal.

What you're looking for is called mp_at_c in the proposal, except it takes a "list" as the first parameter instead of a trailing template parameter. So yours implemented in terms of that one would just be:

template <size_t I, typename... Ts>
using type_pack_element = mp_at_c<mp_list<Ts...>, I>;

This is already in Boost as the Mp11 library, if you want to just use it.
How much class instantiations does require this implementation? And what is the total number of template arguments that will be created? I suspect that the answer is O(N) and O(N^2) respectively, where N = sizeof...(Ts). I'd like to have a solution requiring 0 or O(1) class instantiations.

Barry Revzin

unread,
Oct 11, 2018, 4:11:51 PM10/11/18
to ISO C++ Standard - Future Proposals
Boost is open-source, you can look at the implementation: https://github.com/boostorg/mp11/blob/develop/include/boost/mp11/algorithm.hpp#L305-L320

Andrey Davydov

unread,
Oct 11, 2018, 4:17:57 PM10/11/18
to ISO C++ Standard - Future Proposals
Ah, I see, where it's available Mp11 uses builtin __type_pack_element which I suggest to standardize.

Bryce Adelstein Lelbach aka wash

unread,
Oct 20, 2018, 10:11:49 AM10/20/18
to std-pr...@isocpp.org
This seems like a useful facility, although I wonder if language support for random access to packs would be more elegant.

What happened to P0949? Was it reviewed?

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Matthew Woehlke

unread,
Oct 24, 2018, 12:17:57 PM10/24/18
to std-pr...@isocpp.org, Bryce Adelstein Lelbach aka wash
On 20/10/2018 10.11, Bryce Adelstein Lelbach aka wash wrote:
> This seems like a useful facility, although I wonder if language support
> for random access to packs would be more elegant.

Well, *I* sure thought so... see P0535.

> What happened to P0949? Was it reviewed?

Hadn't seen that before. I am disappointed that it doesn't even mention
P0535.

--
Matthew

Victor Dyachenko

unread,
Oct 25, 2018, 4:16:56 AM10/25/18
to ISO C++ Standard - Future Proposals
Is std::type_pack_element<2,int> just ill-formed or it's a SFINAE?

Andrey Davydov

unread,
Oct 25, 2018, 4:41:31 AM10/25/18
to ISO C++ Standard - Future Proposals
Implemented in Clang now __type_pack_element supports SFINAE (https://godbolt.org/z/g_pIpH), but std::tuple_element_t doesn't.
Do you see some cases where support of SFINAE would be useful?

четверг, 25 октября 2018 г., 11:16:56 UTC+3 пользователь Victor Dyachenko написал:

Victor Dyachenko

unread,
Oct 25, 2018, 4:57:23 AM10/25/18
to ISO C++ Standard - Future Proposals
On Thursday, October 25, 2018 at 11:41:31 AM UTC+3, Andrey Davydov wrote:
Implemented in Clang now __type_pack_element supports SFINAE (https://godbolt.org/z/g_pIpH), but std::tuple_element_t doesn't.
Do you see some cases where support of SFINAE would be useful?

Can't  recall at the moment... But I have analogous class in my code and 3 years ago made it SFINAE-friendly. AFAIK it gives more sensible error messages on errors and in some cases static_asserts are just able to fire.

Louis Dionne

unread,
Nov 1, 2018, 6:43:58 PM11/1/18
to ISO C++ Standard - Future Proposals
Sorry for being late in the game. I originally implemented __type_pack_element in Clang as a workaround for the lack of efficient ways to index parameter packs in the context of template based metaprogramming. At this moment, I do not think that standardizing this facility is a good idea.

C++ wants to move away of template-based metaprogramming and into constexpr value metaprogramming. This is a rather long journey, but the idea is that std::vector should be your type list of the future. In a world like that, indexing a type list can be done with operator[] on the vector, and that should be O(1) compile-time.

Just my .02,
Louis

cpplj...@gmail.com

unread,
Nov 2, 2018, 1:48:26 AM11/2/18
to ISO C++ Standard - Future Proposals


On Thursday, November 1, 2018 at 5:43:58 PM UTC-5, Louis Dionne wrote:
Sorry for being late in the game. I originally implemented __type_pack_element in Clang as a workaround for the lack of efficient ways to index parameter packs in the context of template based metaprogramming. At this moment, I do not think that standardizing this facility is a good idea.

C++ wants to move away of template-based metaprogramming and into constexpr value metaprogramming. This is a rather long journey, but the idea is that std::vector should be your type list of the future. In a world like that, indexing a type list can be done with operator[] on the vector, and that should be O(1) compile-time.

Just my .02,
Louis
 Louis, I don't see how:

template < typename T, typename Alloc = allocator<T> > class vector;

could be used to index into a pack of types since there's
only one type, T, in the template.  I'm guessing you mean
something else?  Maybe:

template< typename[1] T > class vector;

where typename[1] is a new notation meaning maybe something
like a metaclass or maybe a type of types?  And maybe
typename[2] means a type of typename[1]'s?

Could you please provide some more details of how a
std::vector could be used to solve the OP problem?

-Larry

Justin Bassett

unread,
Nov 2, 2018, 11:31:19 AM11/2/18
to std-pr...@isocpp.org
I believe the intent is something like  `std::vector<std::type>` where `std::type` is a value representing a type. So, instead of `template <typename... Ts>`, you would store each T as a value in the vector.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Louis Dionne

unread,
Nov 2, 2018, 11:44:56 AM11/2/18
to std-pr...@isocpp.org
Apologies for the self promotion, but this talk explains that (and more): https://www.youtube.com/watch?v=CRDNPwXDVp0&t=1s. It may be worth it if you are interested by the topic.

Louis


You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/HRx31Xhg7CU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Andrey Davydov

unread,
Nov 2, 2018, 1:54:35 PM11/2/18
to ISO C++ Standard - Future Proposals
Sorry for being late in the game. I originally implemented __type_pack_element in Clang as a workaround for the lack of efficient ways to index parameter packs in the context of template based metaprogramming. At this moment, I do not think that standardizing this facility is a good idea.

C++ wants to move away of template-based metaprogramming and into constexpr value metaprogramming. This is a rather long journey, but the idea is that std::vector should be your type list of the future. In a world like that, indexing a type list can be done with operator[] on the vector, and that should be O(1) compile-time.

I believe that even when vector<metatype> will be available (after C++26?), the following implementation of tuple_element
template<size_t I, typename...Ts>
using type_pack_element = __type_pack_element<I, Ts...>;
will be more efficient than
template<typename...Ts>
constexpr metatype metatypes[] = { $reflect(Ts)... };

template
<size_t I, typename...Ts>
using type_pack_element = $unreflect(metatypes<Ts...>[i]);
In any case it is implementation detail and maintainers of standard library can choose the most efficient way and will change it when reflection will be supported.

Louis Dionne

unread,
Nov 3, 2018, 1:34:00 PM11/3/18
to std-pr...@isocpp.org
My point is that in most cases where you would need to index a parameter pack today, I expect you will instead have a constexpr vector of metatypes in the future. In that case, directly indexing in that vector is the most straightforward way of achieving what you want. If what you have is a parameter pack that you want to index, then yes, using __type_pack_element would be faster and simpler, but I expect that will be rare when metaprogramming moves into the constexpr world.

Louis
 
Reply all
Reply to author
Forward
0 new messages