Reputation: 95
Look at this piece of code:
#include <string>
#include <iostream>
using namespace std;
template <typename T, const T& temp>
void g()
{
cout << temp << endl;
}
static const std::string s = "abc";
int main() {
g<string, s>();
}
When I compile this with Visual C++ 2013 November CTP I get:
“error C2970: 'g' : template parameter 'temp' : 's' : an expression involving objects with internal linkage cannot be used as a non-type argument”
However, I read the following in the C++ 14 standard (14.3.2 [temp.arg.nontype]):
“a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal linkage or”
I interpret this as “constant expression with static storage duration and external linkage” or “constant expression with static storage duration and internal linkage”. In my example above, isn’t the variable s a “constant expression with static storage duration and internal linkage” ?
When I change s to:
std::string s = "abc";
Then it compiles and it works, but isn’t that against the standard because now s is not a “constant expression” anymore.
Can someone shed some light on this? Am I misinterpreting something here?
Upvotes: 8
Views: 2411
Reputation: 361254
Replace static
with extern
:
extern const std::string s = "abc";
The reason is that in C++98/C++03, references with internal linkage was not allowed as template argument.
Also note that just removing static
only would not work if const
is there, because const
objects declared at namespace level has internal linkage (unless it is declared extern
). So you need to use extern
as shown above.
Upvotes: 11
Reputation: 96233
In C++98 the language was (from 14.3.2/1): the name of an object or function with external linkage...
. The change to allow internal linkage was included in C++11.
Your compiler is probably only compiling as the C++98 (or 03) standard, not C++11.
Upvotes: 8