ch12.string_literals_as_template_parameters
C++17 - The complete guide, Ch 12: Dealing with String Literals as Template Parameters
12.1 Using Strings in Templates
-
Over time, the different versions of C++ relaxed the rules for what can be used as template parameters, and this happened again with C++17.
-
Templates now can be used without having to be defined outside the current scope.
-
Non-type template parameters can be only constant integral values (including enumerations), pointers to objects/functions/members, lvalue references to objects or functions, or
std::nullptr_t -
For pointers, before C++17, external or internal linkage was required. However, since C++17, you can have pointers with what is called “no linkage.”
-
However, you still cannot pass string literals directly. For example:
template <const char* str>
class Message {
//...
};
extern const char hello[] = "Hello World!"; // external linkage
const char hello11[] = "Hello World!"; // internal linkage
void foo() {
Message<hello> msg; // OK (all C++ versions)
Message<hello11> msg11; // OK since C++11
static const char hello17[] = "Hello World!"; // no linkage
Message<hello17> msg17; // OK since C++17
Message<"hi"> msgError; // ERROR
}
- That is, since C++17, you still need two lines to pass a string literal to a template. However, you can have the first line in the same scope as the class instantiation.
- This ability also solves an unfortunate constraint: While it has been possible to pass a pointer to a class template since C++11:
template <int* p>
struct A {};
int num;
A<&num> a; // OK since C++11
- It was not possible to use a compile-time function that returned the address but this is now supported:
int num;
//...
constexpr int* pNum() { return # }
A<pNum()> b; // ERROR before C++17, now OK