Consider the following template function :-
template<const char* T>
void fun()
{
}
How can we make a call to this function?
"Easy!". I heard you are saying that way. Just :-
const char* s0 = "hello world";
int main()
{
fun<s0>();
return 0;
}
However, when performing compilation, our Visual C++ gives us the following compilation error :-
error C2975: 'T' : invalid template argument for 'fun', expected compile-time constant expression"Arghh, I know that, just provide array of character, as its length is known during compile-time."
(Note : To understand the difference among char pointer and char array, please refer to
http://support.microsoft.com/kb/44463. We may use sizeof operator, which is evaluated during compile-time, to retrieve string length information from char array, but not char pointer)
So, we would have something like this :-
const char s0[] = "hello world";
int main()
{
fun<s0>();
return 0;
}
OK. It should compiled then, isn't it? However, our compiler again make a complain :-
error C2970: 'fun' : template parameter 'T' : 's0' : an expression involving objects with internal linkage cannot be used as a non-type argumentI heard you are crying.
Take a rest for a while. Let's forget string template parameter at this moment. Let us take a look into internal linkage and external linkage. Consider the following two files :-
// Module0.cpp
////////////////////
//Internal Linkage//
////////////////////
// Constant pointer which is having internal linkage
char* const s0 = "hello";
// Constant string with constant pointer is haing internal linkage
const char* const s1 = "hello";
// Internal linkage
const char s3[] = "hello";
and
// Module1.cpp
////////////////////
//Internal Linkage//
////////////////////
// Constant pointer which is having internal linkage
char* const s0 = "hello";
// Constant string with constant pointer is haing internal linkage
const char* const s1 = "hello";
// Internal linkage
const char s3[] = "hello";
There are two modules. Two modules are having the same set of variable names. However, when we compile and link them together, everything just work fine. This is because they are having internal linkage. The variables are only visible within their own translator unit (object file). No conflict will occur.
How about external linkage? Consider the following two files again.
// Module0.cpp
////////////////////
//External Linkage//
////////////////////
// Constant string which is having external linkage (Early detected during compiled time)
const char* s0 = "hello";
// String with external linkage
char* s1 = "hello";
and
// Module1.cpp
////////////////////
//External Linkage//
////////////////////
// Constant string which is having external linkage
const char* s0 = "hello";
// String with external linkage
char* s1 = "hello";
We will fail during linking time. The external linkage variables are visible among other translator units. Hence, compiler will complain duplicated variable's names being detected.
Till now, I guess you roughly have an idea on why the char array is not being accepted by template function. char array is having internal linkage by default. We need to explicit state that we want external linkage.
Please do not ask me why it must be external linkage. Ask Bjarne Stroustrup. His 14.3.2 "The C++ Programming Language" states that way.
The final piece of code to solve this problem is :-
extern const char s0[] = "hello world";
int main()
{
fun<s0>();
return 0;
}