2

I want to require a template type to be a templates type:

template < template < int beta, typename gamma> class alpha >
gamma foo()
{
    // do stuff with beta, gamma
    gamma c[beta]; 
    alpha a();
    alpha b();
}

I want to have gamma and beta decided by the values I give, so:

foo< hello<2,double> >()

will create a hello<2,double> object instead of alpha, and c will be an array of double with 2 elements.

So, I want to extract the template parameters from the templated class passed to foo.

How would I do this?

Andrew Spott
  • 3,457
  • 8
  • 33
  • 59
  • The question is not clear. Also, `alpha a();` declares a function and not an object. Do you really meant that? – iammilind Jul 03 '12 at 04:14
  • 1
    I'm confused by the 1 in your code snippet and the 2 in the subsequent one. You might have a typo there? – Turix Jul 03 '12 at 04:17
  • alpha is a template class, and you want to extract the template parameter of alpha in a function, is that what you want? – weidi Jul 03 '12 at 04:18
  • @iammilind alpha is the type, a() is the constructor, right? – Andrew Spott Jul 03 '12 at 04:50
  • @weidi: yes!, that is exactly what I want. – Andrew Spott Jul 03 '12 at 04:51
  • @Andrew Spott: No, that's not a "constructor". `alpha a();` is a function declaration: a function `a` that takes no arguments and returns `alpha` object. If you want a default-constructed object, lose the `()`: `alpha a;`. – AnT stands with Russia Jul 03 '12 at 05:04
  • @AndrewSpott, No. You should google about "most vexing parse". In your code `a` is a declaration of function named `a`, returning `alpha`, with no argument. – iammilind Jul 03 '12 at 05:04
  • @AndreyT: Thanks, this is a simplified example, and I forgot that particular detail. I'll fix it, but it isn't super relevant to my question (just that alpha is a class). – Andrew Spott Jul 03 '12 at 05:08
  • @iammilind: Thanks, I've read about the "most vexing parse", I had just forgotten about it. – Andrew Spott Jul 03 '12 at 05:11

1 Answers1

4

The template declaration you provided take a so called template-template parameter (a template parameter of template type). Yet the example of usage you provided attempts to pass an "ordinary" class as an argument (once all template parameters are fixed, template class turns into an "ordinary" class, it is no longer a template).

This immediately means that template-template parameter is not what you need. Template-template parameters serve a completely different purpose. (I won't go into details here).

One possible solution for your problem is to require the argument classes to expose their template arguments through nested types and constants. I.e. your hello template must contain a nested constant beta_value and nested typename gamma_type

template <int BETA, typename GAMMA> class hello 
{
public:
  static const int beta_value = BETA;
  typedef GAMMA gamma_type;
  ...
};

In this case your function will be declared with ordinary type template parameter

template <typename ALPHA> typename ALPHA::gamma_type foo()
{
   // do stuff with beta, gamma
   typename ALPHA::gamma_type c[ALPHA::beta_value]; 
   ALPHA a();
   ALPHA b();
}

If some user forget to follow the convention, the compiler will refuse to compile foo and force that user to update the definition of their argument class.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765