There is a template class A and from it I want to make 2 specific ones: B and C

 #include <iostream> using namespace std; template<const char* s = "hello"> class A { public: void foo(); }; template<const char* s> void A<s>::foo() { cout << s; } typedef A<" world"> B; class C : public A<"!\n"> {}; int main() { A<"hello"> a; B b; C c; a.foo(); b.foo(); c.foo(); return 0; } 

but I get the error:

 prog.cpp:15:19: error: '" world"' is not a valid template argument for type 'const char*' because string literals can never be used in this context typedef A<" world"> B; ^ prog.cpp:17:25: error: '"!\012"' is not a valid template argument for type 'const char*' because string literals can never be used in this context class C : public A<"!\n"> {}; ^ prog.cpp: In function 'int main()': prog.cpp:20:11: error: '"hello"' is not a valid template argument for type 'const char*' because string literals can never be used in this context A<"hello"> a; ^ prog.cpp:23:4: error: request for member 'foo' in 'a', which is of non-class type 'int' a.foo(); ^~~ prog.cpp:24:4: error: request for member 'foo' in 'b', which is of non-class type 'B {aka int}' b.foo(); ^~~ prog.cpp:25:4: error: 'class C' has no member named 'foo' c.foo(); ^~~ 

The code is on ideone.

If A an integer in the pattern instead of a string, then the code works great.

    1 answer 1

    When using untyped template arguments (template non-type arguments) there are a number of limitations , including:

    If you need to go for a pointers, you can use a pointer or a linkage

    This restriction leads to the fact that string literals cannot be used as template arguments:

    In particular, it’s not necessary to make a list of people who are not in a group.

    Because they have neither internal nor external linking. This means that the standard does not guarantee the placement of identical string literals at the same address, leaving the choice of implementation to the compiler developers. Therefore, using A<"hello"> a; in different code fragments could lead to instantiation of various patterns.


    Having dealt with the cause of the error, you can try to eliminate it: we need to pass as a template argument a pointer to an object with a static storage time and an internal or external linking.

     #include <iostream> using namespace std; template<const char* s> class A { public: void foo() { cout << s << "\n"; } }; extern const char p[]; const char p[] = "earth"; extern const char str[]; const char str[] = "world"; template<> class A<str> { public: void foo() { cout << "partial specialization: " << str << "\n"; } }; using B = A<str>; int main() { A<p> a; B b; a.foo(); b.foo(); return 0; }