0

I am trying to pass a template template parameter whom its parameter is a non-type value of type equal to a subtype of a previous template parameter (whew! that was as hard to say as it is to read!), and i'm having some build errors after trying to join the results in a single parametrized templates.

I have the following code (which compiles just fine with g++ 4.4.1 and -std=c++0x):

#include <iostream>

using namespace std;

enum class Labels { A , B };

template <Labels L>
struct LabelTypeMap {
typedef int type_t;
};

template<> struct LabelTypeMap<Labels::B> { typedef double type_t; };

template <bool Enable=true>
struct Hold
{
 typedef Labels enum_t;
};

template <>
struct Hold<true>
{
 typedef Labels enum_t;
};

template< typename Holder , template< typename Holder::enum_t > class typeMap , bool Enable >
struct Whatever
{
 template < typename Holder::enum_t label >
 void Operate(typename typeMap<label>::type_t parameter) {};
};

template< typename Holder , template< typename Holder::enum_t > class typeMap >
struct Whatever< Holder , typeMap , true > : public Holder
{
 template < typename Holder::enum_t label >
 void Operate(typename typeMap<label>::type_t parameter) { cout << "operate on " << parameter << endl; };
};

template < bool Enable >
struct Now {
typedef Hold<true> MyHold;  // <----- check this out!
typedef Whatever< MyHold , LabelTypeMap , Enable > concrete_t;
};

int main() {
 Now< true >::concrete_t obj;
 obj.Operate< Labels::A >( 3.222222222222222222222 );
obj.Operate< Labels::B >( 3.2222222222222222222 );
};

However, Now, look at the Now template: I have two members that are parametrized by booleans. concrete_t depends however on the bool parameter of the enclosing Now template, while MyHold does not. I want to change that, so i replace the Now declaration with this one:

template < bool Enable >
struct Now {
typedef Hold<Enable> MyHold;  // <----- boom!
typedef Whatever< MyHold , LabelTypeMap , Enable > concrete_t;
};

but this gives me the following errors:

error: type/value mismatch at argument 2 in template parameter list for ‘template<class Holder, template<typename Holder::enum_t <anonymous> > class typeMap, bool Enable> struct Whatever’
error:   expected a template of type ‘template<typename Holder::enum_t <anonymous> > class typeMap’, got ‘template<Labels L> struct LabelTypeMap’

I've stared long enough at this and i must say that i completely fail to see why this simple change would trigger an error. any ideas?

EDIT: Here's a minimal exposition of the problem to (hopefully) make it easier to ponder:

$ cat templatetemplate.cc
template <int i>
struct LabelTypeMap { typedef int type_t; };

template <bool>
struct Hold { typedef int type; };

template<typename Holder, template<typename Holder::type> class typeMap>
struct Whatever { };

template <bool Enable>
struct Now { typedef Whatever<Hold<ENABLE>, LabelTypeMap> concrete_t; };

Now<true>::concrete_t obj;

$ g++ -DENABLE=Enable -c templatetemplate.cc
templatetemplate.cc:11: error: type/value mismatch at argument 2 in template parameter list for ‘template<class Holder, template<typename Holder::type <anonymous> > class typeMap> struct Whatever’
templatetemplate.cc:11: error:   expected a template of type ↵
    ‘template<typename Holder::type <anonymous> > class typeMap’, got ↵
    ‘template<int i> struct LabelTypeMap’
marcelo@macbookpro-1:~/play$ 
$ g++ -DENABLE=true -c templatetemplate.cc
(no error)
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
lurscher
  • 25,930
  • 29
  • 122
  • 185
  • What's the connection to C++0x? Ah, spotted it: `enum class`. – Marcelo Cantos Nov 27 '10 at 22:24
  • i've removed the tag until i know if its actually relevant; maybe it is not – lurscher Nov 27 '10 at 22:26
  • It is (at least for `enum class`, although that's not of interest in the question) – icecrime Nov 27 '10 at 22:28
  • I see the same problem if I change `enum class` back to a good old `enum`. I'm not a language expert, but I suspect that gcc has blown a gasket. – Marcelo Cantos Nov 27 '10 at 22:29
  • I think if `Whatever`'s second template parameter `template class typeMap` is supposed to line up with `template struct LabelTypeMap`, it shouldn't be a `typename`? But that breaks even more. – Stéphan Kochen Nov 27 '10 at 22:33
  • @Shtééf: It isn't a `typename` parameter. It is an ordinal (aka non-type) parameter of type `typename Holder::enum_t`, which happens to be `Label` in this instance. So it is, in fact, equivalent to `template – Marcelo Cantos Nov 27 '10 at 23:25

1 Answers1

1

Here's a work-around that compiles, until someone can figure out the mess:

template < bool Enable >
struct Now;

template <>
struct Now<false> {
  typedef Hold<false> MyHold;
  typedef Whatever< MyHold , LabelTypeMap , false > concrete_t;
};

template <>
struct Now<true> {
  typedef Hold<true> MyHold;
  typedef Whatever< MyHold , LabelTypeMap , true > concrete_t;
};
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365