pointer non-type template parameter - c++

I don't really understand why the code below does not compile:
template<const char*>
struct Foo{};
constexpr const char s1[] = "test1";
constexpr const char* const s2 = "test2";
int main()
{
Foo<s1> foo1; // ok
// Foo<s2> foo2; // doesn't compile
}
Uncommenting the last line in main() makes g++ and clang++ emit the errors
error: 's2' is not a valid template argument because 's2' is a
variable, not the address of a variable
and
error: non-type template argument for template parameter of
pointer type 'const char *' must have its address taken
respectively.
My questions are:
Why is s1 instantiation OK and s2 not?
Is there any sane situation where such pointer non-type template parameter is of any use?

In a comment above, vsoftco adds:
seems extremely weird, afaik string literals are not temporaries but are stored for the whole duration of the program, so their address is for sure a compile time constant (or at least that's what I believe)
That's true. However, the standard doesn't specify whether string literals have unique addresses.
Some linkers merge or deduplicate string literals. I have worked on systems where "ello" == "hello"+1 actually evaluates to true. Other linkers are so dumb that "hello" in foo.cc has a different address from "hello" in bar.cc. Heck, some tiny C compilers are so dumb that "hello" can have two different addresses within the same translation unit!
For such a dumb linker (or compiler), should Foo<"hello"> cause one instantiation or two? That is...
const char *sa = "hello world";
const char *sb = "hello world";
assert(sa != sb); // this assertion is permitted to succeed
template<char*> struct F {};
F<"hello world"> fa;
F<"hello world"> fb;
assert(!is_same<decltype(fa), decltype(fb)>::value);
// should we permit this assertion to succeed also?
The Committee admirably refused to open that can of worms, by simply prohibiting the construct.
Now, it's conceivable (to me, at the moment) that sometime in the future the Committee could mandate that all string literals be deduplicated by the same mechanism that implementations currently use for inline and template functions. That is, we can imagine a source-level transformation that turns
const char *sc = "yoo hoo";
into
inline auto& __stringlit_yoo_x20hoo() {
static const char x[] = "yoo hoo";
return x;
}
const char *sc = __stringlit_yoo_x20hoo();
Then there would be only a single instance of __stringlit_yoo_x20hoo (and only a single instance of that function's static array x) anywhere in the program, so the meaning of F<"yoo hoo"> would be unambiguous. The implementation would have to name-mangle the thing unambiguously as well, but that's a simple problem once you've already committed to name-mangling things like F<1+1> and F<FruitType,ORANGE> (which C++ compilers have been doing forever).
...But then you would still have problems with those extremely smart linkers (like the one I worked on) that allow
assert("hello" == "hello\0world"); // this assertion is permitted to succeed
assert(!is_same_v< F<"hello">, F<"hello\0world"> >);
// should we permit this assertion to succeed also?
// Surely this way lies madness.

For 1.:
From [temp.arg.nontype]
1 A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
[...]
(1.3) — a string literal (2.13.5),
s2 holds the address of a string literal, and so cannot be used as the parameter here. s1 on the other hand is an array of char that has been initialized with a string literal, but the value of s1 (when converted to const char*) doesn't point to the string literal used in the initialization.
For 2.:
Function pointers perhaps? Still I can't say I've ever used a pointer as a non-type parameter.

There's a recent change in the relevant standard text, but the code is acceptable in neither version of the standard.
N4140 [temp.arg.nontype]/p1:
1 A template-argument for a non-type, non-template
template-parameter shall be one of:
for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the
template-parameter; or
the name of a non-type template-parameter; or
a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal
linkage or a function with external or internal linkage, including
function templates and function template-ids but excluding
non-static class members, expressed (ignoring parentheses) as & id-expression,
where the id-expression is the name of an object or
function, except that the & may be omitted if the name refers to a
function or array and shall be omitted if the corresponding
template-parameter is a reference; or
a constant expression that evaluates to a null pointer value (4.10); or
a constant expression that evaluates to a null member pointer value (4.11); or
a pointer to member expressed as described in 5.3.1; or
a constant expression of type std::nullptr_t.
N4296 [temp.arg.nontype]/p1:
A template-argument for a non-type template-parameter shall be a
converted constant expression (5.20) of the type of the
template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer
to (or for a pointer type, shall not be the address of):
a subobject (1.8),
a temporary object (12.2),
a string literal (2.13.5),
the result of a typeid expression (5.2.8), or
a predefined __func__ variable (8.4.1).
The N4140 version is the one currently implemented by compilers. The N4296 version is somewhat more relaxed, but in neither case is the address of a string literal an acceptable template argument.
Presumably part of the reason for this is that template arguments must be mangled, and mangling a string literal in a sane way that would work across multiple translation units would be very difficult, if not impossible.

Related

Is it possible to use a pointer as a template argument? [duplicate]

I don't really understand why the code below does not compile:
template<const char*>
struct Foo{};
constexpr const char s1[] = "test1";
constexpr const char* const s2 = "test2";
int main()
{
Foo<s1> foo1; // ok
// Foo<s2> foo2; // doesn't compile
}
Uncommenting the last line in main() makes g++ and clang++ emit the errors
error: 's2' is not a valid template argument because 's2' is a
variable, not the address of a variable
and
error: non-type template argument for template parameter of
pointer type 'const char *' must have its address taken
respectively.
My questions are:
Why is s1 instantiation OK and s2 not?
Is there any sane situation where such pointer non-type template parameter is of any use?
In a comment above, vsoftco adds:
seems extremely weird, afaik string literals are not temporaries but are stored for the whole duration of the program, so their address is for sure a compile time constant (or at least that's what I believe)
That's true. However, the standard doesn't specify whether string literals have unique addresses.
Some linkers merge or deduplicate string literals. I have worked on systems where "ello" == "hello"+1 actually evaluates to true. Other linkers are so dumb that "hello" in foo.cc has a different address from "hello" in bar.cc. Heck, some tiny C compilers are so dumb that "hello" can have two different addresses within the same translation unit!
For such a dumb linker (or compiler), should Foo<"hello"> cause one instantiation or two? That is...
const char *sa = "hello world";
const char *sb = "hello world";
assert(sa != sb); // this assertion is permitted to succeed
template<char*> struct F {};
F<"hello world"> fa;
F<"hello world"> fb;
assert(!is_same<decltype(fa), decltype(fb)>::value);
// should we permit this assertion to succeed also?
The Committee admirably refused to open that can of worms, by simply prohibiting the construct.
Now, it's conceivable (to me, at the moment) that sometime in the future the Committee could mandate that all string literals be deduplicated by the same mechanism that implementations currently use for inline and template functions. That is, we can imagine a source-level transformation that turns
const char *sc = "yoo hoo";
into
inline auto& __stringlit_yoo_x20hoo() {
static const char x[] = "yoo hoo";
return x;
}
const char *sc = __stringlit_yoo_x20hoo();
Then there would be only a single instance of __stringlit_yoo_x20hoo (and only a single instance of that function's static array x) anywhere in the program, so the meaning of F<"yoo hoo"> would be unambiguous. The implementation would have to name-mangle the thing unambiguously as well, but that's a simple problem once you've already committed to name-mangling things like F<1+1> and F<FruitType,ORANGE> (which C++ compilers have been doing forever).
...But then you would still have problems with those extremely smart linkers (like the one I worked on) that allow
assert("hello" == "hello\0world"); // this assertion is permitted to succeed
assert(!is_same_v< F<"hello">, F<"hello\0world"> >);
// should we permit this assertion to succeed also?
// Surely this way lies madness.
For 1.:
From [temp.arg.nontype]
1 A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
[...]
(1.3) — a string literal (2.13.5),
s2 holds the address of a string literal, and so cannot be used as the parameter here. s1 on the other hand is an array of char that has been initialized with a string literal, but the value of s1 (when converted to const char*) doesn't point to the string literal used in the initialization.
For 2.:
Function pointers perhaps? Still I can't say I've ever used a pointer as a non-type parameter.
There's a recent change in the relevant standard text, but the code is acceptable in neither version of the standard.
N4140 [temp.arg.nontype]/p1:
1 A template-argument for a non-type, non-template
template-parameter shall be one of:
for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the
template-parameter; or
the name of a non-type template-parameter; or
a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal
linkage or a function with external or internal linkage, including
function templates and function template-ids but excluding
non-static class members, expressed (ignoring parentheses) as & id-expression,
where the id-expression is the name of an object or
function, except that the & may be omitted if the name refers to a
function or array and shall be omitted if the corresponding
template-parameter is a reference; or
a constant expression that evaluates to a null pointer value (4.10); or
a constant expression that evaluates to a null member pointer value (4.11); or
a pointer to member expressed as described in 5.3.1; or
a constant expression of type std::nullptr_t.
N4296 [temp.arg.nontype]/p1:
A template-argument for a non-type template-parameter shall be a
converted constant expression (5.20) of the type of the
template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer
to (or for a pointer type, shall not be the address of):
a subobject (1.8),
a temporary object (12.2),
a string literal (2.13.5),
the result of a typeid expression (5.2.8), or
a predefined __func__ variable (8.4.1).
The N4140 version is the one currently implemented by compilers. The N4296 version is somewhat more relaxed, but in neither case is the address of a string literal an acceptable template argument.
Presumably part of the reason for this is that template arguments must be mangled, and mangling a string literal in a sane way that would work across multiple translation units would be very difficult, if not impossible.

Non-type reference parameter/argument

Why is it that the template argument of a non-type reference cannot be another reference (g++ 4.8.1):
template <int& N> void test() { }
int x = 5;
int& p = x;
int main(){
test<x>(); //compiles fine
test<p>(); //error: could not convert template argument 'p' to 'int&'|
}
I can't see where from the standard p is violating anything, these seemed the most relevant sections (N3337):
[14.3.2] [.1] A template-argument for a non-type, non-template template-parameter shall be one of:
— for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
— the name of a non-type template-parameter; or
— a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates
and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or .....
[.4]
[ Note: Temporaries, unnamed lvalues, and named lvalues with no linkage are not acceptable templatearguments
when the corresponding template-parameter has reference type.
[.5]
— For a non-type template-parameter of type reference to object, no conversions apply. The type referred
to by the reference may be more cv-qualified than the (otherwise identical) type of the templateargument.
The template-parameter is bound directly to the template-argument, which shall be an
lvalue.
p should be considered an lvalue shouldn't it? The only other thing I could think of was maybe a lack of linkage for references but adding extern int& p = x didn't fix it either.
This is related to the previous question template instantiation with constexpr function failure which I linked to a while ago in the comments, although your case is different.
It looks the example was previously not allowed but support was added in to C++1z via the proposal Allow constant evaluation for all non-type template arguments which opens with:
the syntactic restrictions for pointers, references, and pointers to
members are awkward and prevent reasonable refactorings. [...] The
historical reason for the restriction was most likely that C++
previously did not have a sufficiently strong specification for
constant expressions of pointer, reference, or pointer-to-member type.
However, that is no longer the case. [...]
The specific changes that seems relevant to your case is the rewording of the draft C++ standard section 14.3.2 Template non-type arguments [temp.arg.nontype]/p1 from:
A template-argument for a non-type, non-template template-parameter shall be one of:
[...]
a constant expression (5.19) that designates the address of a complete object with static storage durationtion
and external or internal linkage or a function with external or internal linkage, including function
templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses)
as & id-expression, where the id-expression is the name of an object or function, except that the
& may be omitted if the name refers to a function or array and shall be omitted if the corresponding
template-parameter is a reference; or
[...]
to:
A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of
the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the
value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
a subobject (1.8),
a temporary object (12.2),
a string literal (2.13.5),
the result of a typeid expression (5.2.8), or
a predefined func variable (8.4.1).
and a change of section 5.20 Constant expressions [expr.const]/p4 has the following paragraph on converted constant expressions, which starts out:
A converted constant expression of type T is an expression, implicitly converted to type T, where the converted
expression is a constant expression and the implicit conversion sequence contains only
and this in particular was added:
[...] and where the reference binding (if any) binds directly [...]
Note, the current head version of clang compiles your code in C++1z mode, see it live.
The updated version of the N4268 was the one applied and clang C++1z implementation status section indicates this paper was support from clang 3.6. This code only works in C++1z mode for clang 3.6 and greater.
Using the simplified wording introduced by N4268 (and now in the WD),
A template-argument for a non-type template-parameter shall be a
converted constant expression (5.20) of the type of the template-parameter. For a non-type template-parameter of reference […] type, the
value of the constant expression shall not refer to […]: […cases that don't apply…]
"converted constant expression" is defined in [expr.const]/4:
A converted constant expression of type T is an expression,
implicitly converted to type T, where the converted expression is a
constant expression and the implicit conversion sequence contains
only […] and where the reference binding (if any) binds directly.
Clearly, the reference binds directly. Are x and p constant expressions in this context?
[expr.const]/5:
A constant expression is either a glvalue core constant expression
whose value refers to an entity that is a permitted result of a
constant expression (as defined below), or […]
A permitted result of a constant expression is defined in the next paragraph as
…an object with static storage duration that is either not a temporary object or […]
x and p do refer to an object with static storage duration, but are they core constant expressions in the given context? The answer is yes: As long as their value (or the value of the object p refers to) is not examined by the expression, which it isn't, everything's fine, even for p:
A conditional-expression e is a core constant expression unless the evaluation of e […] would evaluate one of the following expressions:
— an id-expression that refers to a variable or data member of
reference type unless the reference has a preceding initialization and
either
it is initialized with a constant expression
x as the initializer of p is a constant expression (just as it is a valid template-argument for int&), hence p as the template-argument is a constant expression as well.
Note that Clang as of version 3.6 compiles your snippet fine.

Template tricks with const char* as a non-type parameter

I am very well aware that passing directly a const char* as a template non-type parameter is erroneous, since two identical string literals defined in two different translation units may have different addresses (although most of the time the compilers use the same address). There is a trick one may use, see code below:
#include <iostream>
template<const char* msg>
void display()
{
std::cout << msg << std::endl;
}
// need to have external linkage
// so that there are no multiple definitions
extern const char str1[] = "Test 1"; // (1)
// Why is constexpr enough? Does it have external linkage?
constexpr char str2[] = "Test 2"; // (2)
// Why doesn't this work?
extern const char* str3 = "Test 3"; // (3) doesn't work
// using C_PTR_CHAR = const char* const; // (4) doesn't work either
extern constexpr C_PTR_CHAR str4 = "Test 4";
int main()
{
display<str1>(); // (1')
display<str2>(); // (2')
// display<str3>(); // (3') doesn't compile
//display<str4>(); // (4') doesn't compile
}
Basically in (1) we declare and define an array with external linkage, which can then be used as a template parameter in (1'). I understand this very well. However, I don't understand:
Why does the constexpr version (2) work? Does constexpr have external linkage? If not, then defining the same string literal in a different translation unit may lead to duplicate template instantiation.
Why don't (3) and (4) work? It seems perfectly reasonable for me, but the compiler doesn't believe so:
error: 'str3' is not a valid template argument because 'str3' is a variable, not the address of a variable
1. Short answer: It works irrespective of it being declared constexpr, because you're defining an object with static storage duration (that is not a string literal - it stores a copy of the contents of one), and its address is a constant expression. Regarding linkage, str2 has internal linkage, but that's fine - its address can be used as a non-type template argument.
Long answer:
In C++11 and 14, [14.3.2p1] says the following:
A template-argument for a non-type, non-template template-parameter
shall be one of:
[...]
a constant expression (5.19) that designates the address of a complete object with static storage duration and external or internal
linkage or a function with external or internal linkage, including
function templates and function template-ids but excluding non-static
class members, expressed (ignoring parentheses) as & id-expression,
where the id-expression is the name of an object or function, except
that the & may be omitted if the name refers to a function or array
and shall be omitted if the corresponding template-parameter is a
reference;
[...]
So, you can use the address of an object with static storage duration, but the object has to be identified by a name with linkage (internal or external), and the way you're expressing that address is restricted. (String literals are not names and don't have linkage.)
In short, even char str1[] = "Test 1"; works. static char str1[] = "Test 1"; is fine as well; GCC 5.1.0 rejects it, but I think that's a bug; Clang 3.6.0 accepts it.
About str2's linkage, C++11 and 14 [3.5p3] says:
A name having namespace scope (3.3.6) has internal linkage if
it is the name of
[...]
a non-volatile variable that is explicitly declared const or constexpr and neither explicitly declared extern nor previously
declared to have external linkage;
[...]
N4431 has changed that slightly, as a result of DR 1686, to:
a variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external
linkage;
reflecting the fact that constexpr implies const-qualification for objects.
2. Short answer: For C++11 and 14, see above; for draft C++1z, str3 is not a constant expression, as the pointer itself is not constexpr, and it's also the address of a string literal. str4 is constant, but still an address of a string literal.
Long answer:
In the current working draft, N4431, the constraints on non-type template arguments have been relaxed. [14.3.2p1] now says:
A template-argument for a non-type template-parameter shall be a
converted constant expression (5.20) of the type of the
template-parameter. For a non-type template-parameter of reference or
pointer type, the value of the constant expression shall not refer to
(or for a pointer type, shall not be the address of):
a subobject (1.8),
a temporary object (12.2),
a string literal (2.13.5),
the result of a typeid expression (5.2.8), or
a predefined __func__ variable (8.4.1).
And those are all the restrictions. The converted constant expression part is pretty important; the full definition is long, but one part relevant to our case is that the address of an object with static storage duration is such an expression.
Also relevant is that, according to [5.20p2.7], an lvalue-to-rvalue conversion applied to
a non-volatile glvalue that refers to a non-volatile object defined
with constexpr, or that refers to a non-mutable sub-object of such an
object
also satisfies the conditions for being a constant expression. This allows us to use some constexpr pointer variables as non-type template arguments. (Note that simply declaring a variable const is not enough, as it can be initialized with a non-constant expression.)
So, something like constexpr const char* str3 = str1; is fine. It's accepted by Clang 3.6.0 in C++1z mode (and rejected in C++14 mode); GCC 5.1.0 still rejects it - it looks like it hasn't implemented the updated rules yet.
Still, what's wrong with string literals? Here's the problem (N4431 [2.13.5p16]):
Evaluating a string-literal results in a string literal object with
static storage duration, initialized from the given characters as
specified above. Whether all string literals are distinct (that is,
are stored in nonoverlapping objects) and whether successive
evaluations of a string-literal yield the same or a different object
is unspecified.
An implementation is allowed to do lots of things with string literals: mix, match, make them overlap (entirely or partially), make 7 copies from the same translation unit - whatever. That makes the address of a string literal unusable as a non-type template argument.

template instantiation with constexpr function failure

I have template class C that has a non-type but reference template parameter to a type P:
class P {
public:
int x;
int y;
};
template <const P &x>
class C {
public:
const int &f() { return x.x; }
};
I declared a global variable of type P:
P p = {33,44};
I also declared a function that returns a reference to p:
constexpr const P &h() { return p; }
And then tried to use these in the following :
C<p> o; // line 1
C<h()> oo; // line 2
Of course I have no problem with the first instantiation but the second. My compiler complains:
error: non-type template argument does not refer to any declaration
Why is so ? I was unable to find an argument against it in the norm. I am not sure that it is exactly the same problem as in Calling constexpr in default template argument, where the discussion was about point of instantiation of nested instanciation. Here it is more a type problem, but which one ? My function h() returns a reference to a well defined variable of the well defined type (const P &). I expected that some inlining would take place a give the right result but it is not the case. Could you tell me why ?
Declaring the function as inline doesn't change anything to the problem.
Experiments were done with Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn. I also tried with g++-mp-4.8 (MacPorts gcc48 4.8.3_2) 4.8.3 and the error was reported as:
'h()' is not a valid template argument for type 'const P&' because it is not an object with external linkage
It looks like my call to h() (which is a constexpr so compile-time computable) is not seen as such...
I forgot to say that the problem is the same if we try with another reference like this:
const P &pp = p;
and then
C<pp> oo;
this time the first compiler says:
non-type template argument of reference type 'const P &' is not an object
and the second:
error: could not convert template argument 'pp' to 'const P &'
pp is not an object? pp is not of type const P&? Well I can use it as is it one... I know it is a reference but indistinguishable from a native reference, or ?
It looks like this restriction was subject to the following proposal Allow constant evaluation for all non-type template arguments, still trying to determine the status of this proposal. It says:
The syntactic restrictions for pointers, references, and pointers to
members are awkward and prevent reasonable refactorings. For instance:
template<int *p> struct A {};
int n;
A<&n> a; // ok
constexpr int *p() { return &n; }
A<p()> b; // error
and further says:
The historical reason for the restriction was most likely that C++
previously did not have a sufficiently strong specification for
constant expressions of pointer, reference, or pointer-to-member type.
However, that is no longer the case. The status quo is that an
implementation is required to evaluate such a template argument, but
must then discard the result if it turns out to not be null.
In addition to the above, the restriction to entities with linkage is
an artifact of exported templates, and could have been removed when
the linkage restrictions on template type parameters were removed.
and it would remove this section of the note with this restriction:
unnamed lvalues, and named lvalues with no linkage
the whole note reads:
Temporaries, unnamed lvalues, and named lvalues with no linkage are
not acceptable template-arguments when the corresponding
template-parameter has reference type.
Update
The revised version of this proposal N4268 was adopted into the working draft at Urbana and we can see the changes in the latest working draft N4296. The new note reads:
A temporary object is not an acceptable template-argument when the
corresponding template-parameter has reference type
The normative section is 14.3.2 (temp.arg.nontype) paragraph 1 which with this proposal would say:
For a non-type template-parameter of reference or pointer type, the
value of the constant expression shall not refer to (or for a pointer
type, shall not be the address of):
a subobject (1.8),
a temporary object (12.2),
a string literal (2.14.5),
the result of a typeid expression (5.2.8), or
a predefined func variable (8.4.1).
and we can find this new wording in the latest draft standard N4296.
It looks like this change has actually been implemented in clang HEAD see your code working live, using the -std=c++1z flag. This implies the change should be part of C++17, assuming no subsequent changes reverses or alters it.
In the case of
C<h()> oo;
§14.3.2/4 kicks in:
[Note: Temporaries, unnamed lvalues, and named lvalues with no linkage are not acceptable template-
arguments when the corresponding template-parameter has reference type.
(emphasis mine)

const variable as non-type template parameter (VARIABLE cannot appear in a constant-expression)

Why does this work?
char __nontype[] = "foo";
typedef TemplateClass<T, __nontype> MyClass;
But this (with a constant variable) not?
const char __nontype[] = "foo";
typedef TemplateClass<T, __nontype> MyClass;
Compiler Error:
error: ‘__nontype’ cannot appear in a constant-expression
error: template argument 2 is invalid
The difference is because const affects the linkage. It works if you add extern. That said, as far as I can tell:
14.3.2 Template non-type arguments [temp.arg.nontype]
A template-argument for a non-type, non-template template-parameter shall be one of:
an integral constant expression (including a constant expression of literal class type that can be used as an integral constant expression as described in 5.19); or
the name of a non-type template-parameter; or
a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
a constant expression that evaluates to a null pointer value (4.10); or
a constant expression that evaluates to a null member pointer value (4.11); or
a pointer to member expressed as described in 5.3.1.
it should also work without extern. The object is allowed to have internal linkage, but your compiler does not yet support that. This is one of the changes in C++11, the previous C++ standard did not allow it.
The error says it: the result is not a constant expression (it is known at link time, but not compile time).
Here is an example that would work:
typedef const char *nontype_t;
template <nontype_t> struct Y {};
char hello[] = "hello";
constexpr char* world = hello;
int main()
{
Y<hello> a;
}