0

I have the following class:

template<int p, int q, int r>
struct ga { // geometric algebra with signature (p,q,r)
  static const int d = p+q+r;
  
  struct mv { ... }; // multivector in this GA
  
  template<int g>
  struct gmv : mv { ... }; // multivector in this GA with grade g
};

And I want to make a function outside of this class that takes a ga::mva

template<int p, int q, int r>
void print(ga<p,q,r>::mv) { ... }

However this gives the following error message:

error: variable or field 'print' declared void
void print(ga<p,q,r>::mv v) {
     ^~~~~

error: expected ')' before 'v'
void print(ga<p,q,r>::mv v) {
          ~             ^~
                        )

These error messages seem weird to me and suggests the compiler is not properly parsing my code.

I also tried

template<int p,int q,int r, ga<p,q,r> g>
void print(g::mv v) { ... }

Giving the declared void error and also

error: 'g' is not a class, namespace, or enumeration

It works if I do

using pga = ga<3,1,0>
void print(pga::mv v) { ... }

So how can I implement the general version?

Edit: Full MRE

template<int p, int q, int r>
struct ga { // geometric algebra with signature (p,q,r)
  static const int d = p+q+r;
  
  struct mv {}; // multivector in this GA
  
  template<int g>
  struct gmv : mv {}; // multivector in this GA with grade g
};

template<int p, int q, int r>
void print(typename ga<p,q,r>::mv v) {}

int main() {
  using pga = ga<3,1,0>;
  pga::gmv<2> v;
  print(v);
}
  • you need `typename` like this: `void print(typename ga

    ::mv) { }`

    – 463035818_is_not_an_ai Sep 01 '23 at 11:51
  • 2
    btw please read about [mcve]. I had to fix several typos in your code that are unrelated to the question to reproduce the error with my compiler – 463035818_is_not_an_ai Sep 01 '23 at 11:52
  • the compiler wrongly interprets `ga

    ::mv` as the initializer for the variable `print` of type `void` and then complains that you cannot declare `print` to be of type `void`. The keyword `typename` helps the compiler to realize that `ga

    ::mv` is a type

    – 463035818_is_not_an_ai Sep 01 '23 at 11:54
  • Thank you, I was not aware of typename (though it seems like a hack for the compiler). I have added the MRE without being split up. Now there is a new issue: it does not figure out that `ga

    ::gmv` is a specialisation of `ga

    ::mv`, But I guess that should be asked as a seperate question.

    – Jelmer Firet Sep 01 '23 at 12:27
  • template arguments cannot be deduced like this. `print<3,1,0>(v)` should work. Though, yes its a different question. – 463035818_is_not_an_ai Sep 01 '23 at 12:52
  • `typename` is not a "hack". Consider that there might be a specialization where `ga

    ::mv` is not a type. It could be an `int` or anything else.

    – 463035818_is_not_an_ai Sep 01 '23 at 12:53
  • I would recommend to reconsider this nesting of types. Some things get much simpler if you have three seperate templates `ga`, `mv` and `gmv` – 463035818_is_not_an_ai Sep 01 '23 at 12:54
  • you didnt show the implementation of `print`, but maybe the simple alternative can work: `template void print(const T&)` – 463035818_is_not_an_ai Sep 01 '23 at 12:55

0 Answers0