65.9K
CodeProject is changing. Read more.
Home

Passing a const character * as a template argument

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1 vote)

Jun 30, 2011

CPOL
viewsIcon

27867

Consider a class template of the form (the method cout is just explanatory):template struct A { static void cout() { std::cout << str << std::endl; };};How can this template be instantiated?From the C++ standard can be understood that the address...

Consider a class template of the form (the method cout is just explanatory):
template<const char* str> struct A {
    static void cout() {
        std::cout << str << std::endl;
    };
};
How can this template be instantiated? From the C++ standard can be understood that the address of an object with external linkage may be passed, but nothing else. So passing string literals is not possible:
struct B
void f() {
    typedef A<"Test 1"> A1; // VC++ 2008 C2762
    A1::cout();
}
Option 1 A C-style string is declared extern to avoid the limitation through the standard.
// extern const char* s = "Test 2"; // VC++ 2008 error C2975 *)
extern const char s[] = "Test 2";   // OK

void f() {
    typedef A<s> A2;
    A2::cout();
}
Option 2 Also, static class members have external linkage. This resembles Ataul's approach:
struct B
{
    static const char s[];
};
 
const char B::s[] = "Test 3";

void f() {
    typedef A<B::s> A3; 
    A3::cout();
}
As it can be seen, passing C-style strings as template parameters requires quite a lot of overhead and might have other negative consequences (option 1 practically gives global scope to s). I wonder if there is any real-life use for it. *) My interpretation of this error is: For an array, information about its size is stored (it can be retrieved via the sizeof operator). When declaring s as const char*, the size information is lost and the compiler does not know how much text is inside the string.