C++, templates: get type of the item

10,328

Solution 1

You can typedef the template parameter T in the struct and use std::list::value_type to get the type stored in the struct AB if you don't use C++11:

#include<list>
#include<iostream>

template <typename T>
struct AB
{
    T a, b;

    typedef T value_type;

    AB( ) 
    : 
        a (0), 
        b (0) 
    {}

};


template <typename T>
struct ABList
{
    typedef std::list < AB <T> > Type;
    typedef T Type2;
};

template <typename List>
void test ( List & l )
{
    typename List::iterator i_l = l.begin();

    typename List::value_type::value_type& Listval = i_l->a;

    std::cout << Listval << std::endl;
}

template <typename List>
void test (List l, typename List::value_type::value_type val )
{
    std::cout << "test" << std::endl;
}

int main(int argc, char* argv[])
{
    ABList <double> ::Type intervals;

    double x = 7.0;

    test(intervals, x);

    return 0;
}

Solution 2

In C++11, just use auto:

auto val = (*il).a;

And if you need to refer to that type later, you can use decltype(val).

In C++03, you can get the underlying type for a standard container type L as:

L::value_type

So in your case it should be:

typename List::value_type

In your case, however, that would give you the type AB, and not the type of AB::a. If you need to be able to retrieve at compile time the type T for an instance of the AB template, you need to provide some type alias inside AB. For instance:

template <typename T>
struct AB
{
    typedef T value_type;
//  ^^^^^^^^^^^^^^^^^^^^^

    T a, b;

    AB <T> ( ) : a ( 0.0 ), b ( 0.0 ) {}
};

Then you could do:

typename List::value_type::value_type val = (*il).a;

If you do not want to alter the definition of AB just for this purpose, you can define a separate type trait, such as the following:

template<typename T>
struct underlying_type_of;

template<typename T>
struct underlying_type_of<AB<T>>
{
    typedef T type;
};

You could then get the underlying type T of AB<T> as shown below:

typename underlying_type_of<typename List::value_type>::type val = (*i_l).a;
Share:
10,328
justik
Author by

justik

Updated on June 04, 2022

Comments

  • justik
    justik almost 2 years

    There are two structures:

    template <typename T>
    struct AB
    {
        T a, b;
    
        AB <T> ( ) : a ( 0.0 ), b ( 0.0 ) {}
    };
    
    
    template <typename T>
    struct ABList
    {
        typedef std::list < AB <T> > Type;
    typedef T Type2;
    };
    

    and a function

    template <typename List>
    void test ( List l )
    {
        List::iterator i_l = l.begin();
    
        //Here *i_l type is needed instead of double
        double val = (*il).a;
    
    }
    

    Is there any way how to get *i_l templatized type (here double), i.e,

    std::list::Item type
    

    without passing any other parameter if

    int main(int argc, char* argv[])
    {
    ABList <double> ::Type intervals;
    
    test (intervals);
    
    
    return 0;
    }
    

    Thanks for your help, C++ 03 is preferred.

    Updated question

    If a templatized type

    std::list::Item type
    

    represents a formal parameters of test(), this solution

    template <typename List>
    void test ( List l, typename List::value_type::value_type val )
    {
      ...
    }
    
    int main(int argc, char* argv[])
    {
    ABList <double> ::Type intervals;
    double x = 7.0;
    
    test <ABList<double>> (intervals, x);
    
    return 0;
    }
    

    does not work... The following error occurs:

    error C2770: invalid explicit template argument(s)
    

    The version

    test (intervals, x);
    

    causes another error:

    Failed to specialize function template 'void test(List,List::value_type::{ctor})'
    
  • justik
    justik almost 11 years
    @ tomislav: Thanks, but if typename List::value_type::value_type Listval represents a formal parameter of the test method, it does not work.
  • tmaric
    tmaric almost 11 years
    not sure I get what you mean: the formal parameter of the test function is the List template parameter, as long as the List is STL compliant it will have value_type typedef in its public interface, and if you extend the structure stored in List to do the same, there is no problem... or am I missing something?
  • justik
    justik almost 11 years
    @ tomislav: omitting specialization causes another error :-(.
  • tmaric
    tmaric almost 11 years
    @justik: I've modified the code, it compiles on g++ (Ubuntu 4.4.3-4ubuntu5.1) 4.4.3
  • justik
    justik almost 11 years
    @ tomislav: Yes, you are right. I checked g++ (OK), but VS 2010 compiler does not work... I am going to create a new thread with the simplified example... Once again, thanks for your help.