typename
Is Required By “Dependent Names”
Dependent names are names that are dependent on the type of a template parameter. To instantiate instances of them, or to simply use them as types, one needs to use the keyword typename.
Consider the below snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
// namespace MyClass { // can't be namespace, because typename T expects a type, such as class/struct
struct MyClass {
struct constant {
static constexpr int value = 42;
};
};
template <typename T>
void exampleFunction() {
typename T::constant myConstant; // No 'template' keyword needed
// value is a static member, and it's accessible to the class itself
std::cout << "Value: " << myConstant.value << std::endl;
}
::
means type within a typetypename T
can’t take in a namespace. It has to be a type. It is to create an object of the type Ttypename T::constant myConstant
can access static members, likemyConstant.value
Non-Type Template Parameters
Non Type template parameters are compile time constants that customizes a struct. Some notes include:
Foo<9>
is a different instantiation ofFoo<10>
1
2
3
4
5
6
7
8
9
10
11
12
template <int N>
struct Foo{
static const int i = N;
};
int main()
{
Foo<9> f;
std::cout << f.i << std::endl;
// Print the static class member
std::cout << Foo<10>::i << std::endl;
}
template
Keyword Is Required To Disambiguate
Consider the below snippet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <type_traits> // For std::remove_pointer
template <class T>
void f(T &x) {
// Resolve the base type of T if T is a pointer
using BaseType = typename std::remove_pointer<T>::type;
// So BaseType is FTemplates
// template function variable() needs to be accessed with an explicit "template"
// BaseType::template is needed to indicate constant is a nested template inside Basetype
x->template variable<typename BaseType::template constant<3>>();
}
struct FTemplates {
// Nested template
template <int N>
struct constant {
static constexpr int value = N;
};
// Member template
template <typename T>
void variable() {
std::cout << "variable: " << T::value << std::endl;
}
};
int main() {
FTemplates f_tmp;
FTemplates *f_ptr = &f_tmp;
// Call f with a pointer to f_templates
f(f_ptr); // Outputs: variable: 3
return 0;
}