views:

102

answers:

2

hello.

I believe I had seen macro in boost that recovers template template parameters, for example:

template<class>
struct parameters;

#define parameters(T) template<class A> \
          struct parameters<T<A> > { typedef A type1; };

is there one like this, or am I wrong?

Thank you

+1  A: 

delctype support in C++0x makes this fairly trivial to implement:

template<template <typename> class Parent, typename Param1>
Param1 get_type(Parent<Param1> const &input) { return Param1(); }

SomeTpl<int> some_obj;
delctype(get_type(some_obj)) x;

(Though you need a separate get_type definition for templates with 2, 3, 4, etc parameters.)

Unfortunately, I don't think there is a way to do this without decltype, because to do so required automatic the type-deduction provided by function templates (which is not available for class templates) and so there's no way to make a typedef that way.

I don't know off-hand if boost has anything like this already, but if they do it will still require your compiler to support decltype, but since decltype is so new there is not a lot of stuff in boost that uses it yet (though there is some).

SoapBox
A: 

I have learned to trust Johannes' statements, so I'm a bit confused, since this seems to compile Ok for me with VC10 and prints the expected int:

#include <iostream>
#include <typeinfo>

template< class T >
class steal_it;

template< typename U, template<typename> class C >
struct steal_it< C<U> > { 
    typedef U result_t;
};

template< typename T >
class foo {};

template< typename T >
void test_it(T)
{
    typename steal_it<T>::result_t bar = 42;
    std::cout << typeid(bar).name() << '\n';
}

int main(){

    test_it( foo<int>() );

    return 0;
}

Of course, since I didn't check with any other compilers, this could just be VC fooling me again...

sbi
Thanks for your trust :) Thouh I wonder what makes you think i would say it wouldn't work. This is a special case too, because you have to assume the template has one type parameter. In this case you can use the function parameter for deduction also directly `template<template<typename> class C, typename U> void test_it(C<U>) { U bar = 42; /* ... */ }`. In my other answer i was referring to entirely arbitrary template parameter lists, for which this isn't possible anymore :) You can even solve this without evaluating the expression `foo<int>()` by using the conditional operator trick.
Johannes Schaub - litb
@Johannes: But what prevents you from specializing `steal_it` for 1-50 template parameters and thus get a solution that's generic for all practical means?
sbi
@sbi it can't work because you require all parameters to be types. You couldn't pass `boost::array` to such a template, for example.
Johannes Schaub - litb
@Johannes: But a non-type argument wouldn't work in a context a type would be useful anyway. In order to deduce arguments, you have to know before-hand whether they are types or something else. And if you know an argument to be a size, you could deduce that, too, in the same way.
sbi
@sbi no i mean if you want to get a type parameter, then you still have to be concerned with the other parameters too. So for `boost::array` even if you are only interested in the type, then you still have to deduce the size too. And even if you only have a parameter list full of "sizes", that's not enough because you have to know the precise type of the sizes... That's just impossible to solve - would need pratically infinitely overloads. Also, your function can nicely be overloaded but won't give the caller the type back. You have to use class templates for that which cannot be overloaded.
Johannes Schaub - litb
@Johannes: I'd say it the other way around: In _theory_, you need an infinite number of overloads. In _practice_ the set of templates you're working with is rather limited and this is usually doable. And that function is named `test_it()` for a reason. It's just a test to see whether `steal_it<>` works, nothing more.
sbi