String literal as non type template parameter
Unfortunately it is not possible to have template with string literal as a non type parameter. Until C++11 reason was that string literals had internal linkage, while non type template parameters allowed only external linkage pointers. It makes sense because templ_class should have the same typeid in all translation units. It kind of could work with string pooling enabled – which is availabe for both gcc and msvc. After C++11 the reason is more of that string literals does not match any of the allowed entities as template parameter.
You can use character array initialized with string literal as non type parameter. It compiles both with g++ and msvc:
#include <typeinfo> template<const char* STR> class MyStr {}; extern const char my_string[]; const char my_string[] = "alfabet"; extern const char my_string2[]; const char my_string2[] = "alfabet"; // or use constexpr //constexpr const char my_string[] = "alfabet"; //constexpr const char my_string2[] = "alfabet"; extern const char* my_string_pc; const char* my_string_pc = "alfabet"; int main(){ // This fails with: // main.cpp:30:31: error: 'my_string_pc' is not a valid template argument because 'my_string_pc' is a variable, not the address of a variable // typedef MyStr<my_string_pc> str_type3; typedef MyStr<my_string_pc> str_type3; // Below compiles, but gives different types typedef MyStr<my_string> str_type1; typedef MyStr<my_string2> str_type2; // This fails static_assert(std::is_same<str_type1, str_type2>::value, ""); return 0; }
EDIT:
After writing it I have found in standard ([temp.arg.nontype]) the actual reasoning for all above:
[ Note: A string literal (2.14.5) does not satisfy the requirements of any of these categories and thus is not
an acceptable template-argument. [ Example:
template<class T, const char* p> class X { / ... / }; X<int, "Studebaker"> x1; // error: string literal as template-argument const char p[] = "Vivisectionist"; X<int,p> x2; // OK
—end example ] —end note ]
Leave a Reply