Why is this valid code?

See the following:

1
2
3
4
5
6
7
8
9
10
11
 #include <iostream>

using namespace std;

template<class X*> void y() {}

int main()
{
    return 0;
}


Why can I create a template with the parameter 'class X*'? If I were to replace the keyword class with "typename", like so:

1
2
3
4
5
6
7
8
9
10
11
 #include <iostream>

using namespace std;

template<typename X*> void y() {} //ERROR!!

int main()
{
    return 0;
}


Now there is an error. Why does the first case work but the second case fails? Furthermore, what is the point of making the template parameter "class X*"? How do you even instantiate such a template?
Last edited on
How do you even instantiate such a template?
y<nullptr>();
It's a non-type template parameter.

If you had declared a class T prior
class T;
Then you could have written
template <T*> void y() {}

The class here is just a disambiguator, it's only required in cases where non-type hiding is involved:
1
2
3
4
5
6
7
8
9
class X {};
int main()
{
  X a; // declares a variable of type X named a
  class X b; // declares a variable of type X named b
  class X X; // declares a variable of type X named X
  // X c; // wrong: the identifier X now refers to the variable X
  class X d; // ok - "class X" unambigously refers to the type X
}
Last edited on
I still don't quite understand why typename can't be used interchangeably for the template parameter in that example, because it normally can be. It's because of the pointer syntax, but I still don't understand how that's wrong.
https://en.cppreference.com/w/cpp/language/template_parameters

Because it is not a type template parameter.
These are:
1
2
3
template<class    X> void y() {} // X is replaced with typename
template<typename X> void y() {} // X is replaced with typename
template<typename X = std::vector<double> > void y() {}


Non-type template parameter
1
2
3
4
5
template<int  X> void y() {} // 'int' is typename, X is name of value
template<int* X> void y() {} // X is name of value
template<class T* X> void y() {} // 'class T' is typename, X is name of value
template<class T*> void y() {} // 'class T' is typename, unnamed value
template<class T* X = nullptr> void y() {} // with default value 

Topic archived. No new replies allowed.