value_type<T>

469 views
Skip to first unread message

John McFarlane

unread,
Dec 10, 2016, 9:49:45 PM12/10/16
to ISO C++ Standard - Future Proposals
A type trait that, given a container type, yields the element type:

value_type_t<string[10]> // string
value_type
<std::vector<const float *>>::type // const float *
value_type_t
<std::list<array<char, 5>>> // array<char, 5>

Possible implementation along the lines of

template<class T>
struct value_type;

template<class T, std::size_t N>
struct value_type<T[N]> {
   
using type = T;
};

template<class T>
struct value_type<std::vector<T>> {
   
using type = T;
};

template<class T>
struct value_type<std::list<T>> {
   
using type = T;
};

// and everything else for which there is begin(T)

template<typename T>
using value_type_t = typename value_type<T>::type;

although there may well be a simpler approach which exploits begin, end or member value_type.

Derek Ross

unread,
Dec 10, 2016, 10:31:32 PM12/10/16
to ISO C++ Standard - Future Proposals
The following seems to work:


template<typename T>
struct value_type
{
   
using type = decltype(*std::begin(*((T*)(NULL))));
};

int main()
{
   cout
<< typeid(value_type<string[10]>::type).name() << endl;    
   cout
<< typeid(value_type<std::vector<const float *>>::type).name() << endl;    
   cout
<< typeid(value_type<std::list<std::array<char, 5>>>::type).name() << endl;
   
   cout
<< typeid(string).name() << endl;
   cout
<< typeid(const float *).name() << endl;
   cout
<< typeid(std::array<char, 5>).name() << endl;
}

...output...
Ss
PKf
St5arrayIcLm5EE
Ss
PKf
St5arrayIcLm5EE

Tony V E

unread,
Dec 10, 2016, 11:08:35 PM12/10/16
to ISO C++ Standard - Future Proposals
Use declval<T>() instead of casting null.

Sent from my BlackBerry portable Babbage Device
From: Derek Ross
Sent: Saturday, December 10, 2016 10:31 PM
To: ISO C++ Standard - Future Proposals
Subject: [std-proposals] Re: value_type<T>

--
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/45df670c-da8b-453c-9a87-b2936493fc75%40isocpp.org.

John McFarlane

unread,
Dec 11, 2016, 12:43:22 AM12/11/16
to ISO C++ Standard - Future Proposals
On Saturday, December 10, 2016 at 8:08:35 PM UTC-8, Tony V E wrote:
Use declval<T>() instead of casting null.

You also need to remove the reference. This might work:

template<class T>
struct value_type {
   
using type = typename std::remove_reference<decltype(*std::begin(declval<T&>()))>::type;
};

Regardless, I would prefer not to ever have to type something like this! I've needed it before and gone hunting online for a concise solution. And it came up in relation to a proposal on SG14:
https://groups.google.com/a/isocpp.org/d/topic/sg14/Md3D_7vMpgs/discussion

Marc

unread,
Dec 11, 2016, 6:26:43 AM12/11/16
to ISO C++ Standard - Future Proposals

What type do you want it to return for
std::vector<bool>
? I'd rather get bool than the proxy.
Note that Boost calls this range_value.

Thiago Macieira

unread,
Dec 11, 2016, 1:47:15 PM12/11/16
to std-pr...@isocpp.org
On sábado, 10 de dezembro de 2016 21:43:21 PST John McFarlane wrote:
> On Saturday, December 10, 2016 at 8:08:35 PM UTC-8, Tony V E wrote:
> > Use declval<T>() instead of casting null.
>
> You also need to remove the reference. This might work:
>
> template<class T>
> struct value_type {
> using type = typename std::remove_reference<decltype(*std::begin(declval
> <T&>()))>::type;
> };

This should be the same as

std::iterator_traits<decltype(begin(declval<T&>()))>::value_type

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center

John McFarlane

unread,
Dec 11, 2016, 3:11:43 PM12/11/16
to ISO C++ Standard - Future Proposals
On Sunday, December 11, 2016 at 10:47:15 AM UTC-8, Thiago Macieira wrote:
This should be the same as

 std::iterator_traits<decltype(begin(declval<T&>()))>::value_type

Looks good, thanks.

John McFarlane

unread,
Dec 11, 2016, 3:23:02 PM12/11/16
to ISO C++ Standard - Future Proposals
On Sunday, December 11, 2016 at 3:26:43 AM UTC-8, Marc wrote:
What type do you want it to return for
std::vector<bool>
? I'd rather get bool than the proxy.
Note that Boost calls this range_value.

I'd opt for `bool` because std::vector<bool>::value_type is bool. As in the previously-mentioned use case, this type would be a special case regardless as container storage is not sizeof(Element) * size(Container).

Another question that occurres is name: `value_type` versus `element_type` versus something else. Neither is used in the standard exclusively to represent the element of a container. So either `value_type` is ambiguous, a different name is found, or (my preference) it accepts types which are not containers, e.g. iterator_traits, integral_constant etc..
Reply all
Reply to author
Forward
0 new messages