Reputation: 5639
It's rather common that container templates contain a value_type
typedef. This makes it easy to create other templated code, most recently concepts, which are able to extract the T
if only having been given Container
and not Container<T>
.
However, not all containers (or other templated classes) define such a value_type
, especially older ones.
Is it possible to get to the contained T
even without it?
I know there are tricks like "if it is an iterator then .begin()
should return a value of that type", but that does not help us to e.g. write a concept-requirement that checks whether a class's .begin()
indeed follows the requirements that iterators have.
Upvotes: 2
Views: 419
Reputation: 60238
Here's a solution that's similar to Quimby's solution but using partial template specialization instead:
template<typename...>
struct inner_type_impl;
template<template<typename...> typename C, typename T, typename...Args>
struct inner_type_impl<C<T,Args...>>
{
using type = T;
};
template<typename T>
using inner_type = typename inner_type_impl<T>::type;
Here's a demo that's borrowed from Quimby's solution.
Upvotes: 4
Reputation: 19123
Class template specialization or template argument deduction can be used to implement this. Something like the following should work as long as the inner type is the first template argument:
#include <type_traits>
// Consider the first template argument to be the inner type.
template<template<typename,typename...>class C,typename T,typename...Args>
auto inner_type_impl(const C<T,Args...>* v)->T*{return nullptr;};
template<typename T>
using inner_type = std::remove_pointer_t<decltype(inner_type_impl((T*)nullptr))>;
template<typename T>
struct Container;
// Will still deduce T
template<typename T,typename...Extras>
struct ContainerExtraParams;
static_assert(std::is_same_v<int,inner_type<Container<int>>>);
static_assert(std::is_same_v<int,inner_type<ContainerExtraParams<int,double,float>>>);
I use pointers to make the code valid in evaluated contexts too. Contrary to a possible solution involving std::declval
.
Upvotes: 3