Search code examples
c++c++11templatesc++14string-literals

Why can an array of char be a template parameter but a const char* can't


I'm trying to pass a literal string as a template parameter in a C++14 project. Google told me that I can do as below:

struct Test {
    static const char teststr[];

    template<const char* str>
    void p() {std::cout << str;}
};

const char Test::teststr[] = "Hello world!";

int main() {
    Test t;
    t.p<Test::teststr>();
}

It did work.

However, if I use const char*, instead of const char []. It won't work.

struct Test {
    static const char* teststr;

    template<const char* str>
    void p() {std::cout << str;}
};

const char* Test::teststr = "Hello world!";

int main() {
    Test t;
    t.p<Test::teststr>();
}

Now it doesn't work. The compiler told me that 'Test::teststr' is not a valid template argument because 'Test::teststr' is a variable, not the address of a variable.

Well, I don't know what it meant.


Solution

  • The error message from the compiler is clear enough:

    error: 'Test::teststr' is not a valid template argument because 'Test::teststr' is a variable, not the address of a variable

    So you need:

    #include <iostream>
    
    struct Test {
        static const char* teststr;
    
        template<const char **str>
        void p() {std::cout << *str;}
    };
    
    const char* Test::teststr = "Hello world!";
    
    int main() {
        Test t;
        t.p <&Test::teststr>();
    }
    

    And then it works - the point being that [the contents of] a variable is not a compile-time constant, whereas the address of a variable (if it's a static or global variable) is.