Gerard
Gerard

Reputation: 2860

get decltype of template argument

I often want to get the decltype of a class template argument in order to use it further, like in a loop which I have stripped and simplified to show my problem:

template <typename T>
class Foo {
public:
    T type; //This is my hack to get decltype of T
};

template <typename T>
class Bar {
public:

};

int main() {
    for(auto& foo : fs) {
        //Is there some way to get the decltype of the template without having to refer to some arbitrary T member of Foo?
        auto bar = someFunction<decltype(foo.type)>();
    }
}

Is there a way to get the decltype of the template argument without doing this hack? If not, what is the best workaround to get the decltype of such a value?

Upvotes: 7

Views: 14331

Answers (2)

Jarod42
Jarod42

Reputation: 218323

You may create a type_traits:

template <typename C>
struct get_template_type;

template <template <typename > class C, typename T>
struct get_template_type<C<T>>
{
    using type = T;
};

and then you use it (assuming C = Foo<T>, you will have T)

typename get_template_type<C>::type

Live example

EDIT: For classes with multiple template parameter, to retrieve the first one:

template <template <typename > class C, typename T, typename ... Ts>
struct get_template_type<C<T, Ts...>>
{
    using type = T;
};

Upvotes: 10

rubenvb
rubenvb

Reputation: 76795

EVerything in the Standard library just has class-local typedefs:

template<typename T>
struct Bla
{ using value_type = T; }

So you can do:

template<typename T>
void f(const T& t)
{
  typename T::value_type some_var_with_template_type;
}

Alternatively, you can modify the calling function:

template<template<typename> class Class, typename T>
void f(const Class<T>& c)
{
  T some_var_with_template_type;
}

But that would impose limitations on usability and generality. Because for example, if there were a Class with more than one template param, this would fail (although variadic templates could be used to work around this). Variadic template version:

template<template<typename, typename...> class Class, typename T, typename... ArgTypes>
void f(const Class<T, ArgTypes...>& t)
{
  T some_var_of_template_type;
}

Note how the value_type typedef is by far the cleanest and most idiomatic solution.

Some code to show how the functions would need to be written and used.

Upvotes: 1

Related Questions