I have some very simple (C++11) code which the latest clang (version 3.4 trunk 187493) fails to compile, but GCC compiles fine.
The code (below) instantiates the function-template foo
with the function-local type Bar
and then tries to use its address as a non-type template parameter for the class-template Func
:
template<void(*FUNC_PTR)(void)>
struct Func {};
template<typename T> extern inline
void foo() {
using Foo = Func<foo<T>>;
}
int main() {
struct Bar {}; // function-local type
foo<Bar>();
return 0;
}
clang emits the following error:
error: non-type template argument refers to function 'foo' that does not have linkage
However, if I move type Bar
to global scope (by taking it out of the function), then clang compiles it fine, proving the issue is with the type being function-local.
So is clang correct to emit this error, or does the standard not support this (in which case GCC is being too lenient by allowing it)?
EDIT #1 : To be clear, this is not a duplicate of this question since the 'cannot use local types as template parameters' restriction was removed in C++11. However, it's still unclear if there are linkage implications involved with using a local type, and whether clang is correct or not in emitting this error.
EDIT #2 : It has been determined that clang was correct to emit the error for the above code (see answer from @jxh), but that it incorrectly also emits an error for the following code (with
using
declaration moved from foo<Bar>()
scope to main()
scope):
template<void(*FUNC_PTR)(void)>
struct Func {};
template<typename T> extern inline
void foo() {}
int main() {
struct Bar {};
using F = Func<foo<Bar>>;
return 0;
}
By definition of no linkage in C++.11 §3.5 Program and linkage ¶2, I originally believed
foo<Bar>
has no linkage since it cannot be referred to by name by any other scope except that which defined the typeBar
(ie,main()
). However, this is not correct. This is because the definition of a name with external linkage is described as:And for a template function, this will always be the case. This is because there is one other scope from which the name can be referred. Namely, the template function can refer to itself. Therefore,
foo<Bar>
has external linkage. zneak's answer, EDIT 2, has an e-mail thread with the clang developers confirming thatfoo<Bar>
should have external linkage.Thus, from C++.11 §14.3.2 Template non-type arguments ¶1:
The most relevant bullet is the third bullet. Since
foo<bar>
has external linkage, passing it as a non-type template-parameter should be fine.I'm late to the party, but standard says that type-local functions don't have linkage (§3.5:8):
Same section goes on to say:
And, as a matter of fact, Clang will allow this:
And will reject it without the anonymous namespace.
EDIT 1: As jxh notes, the names are also defined in the same translation unit, so I'm not sure what to think of this one.
EDIT 2: The guys at clang confirm it's a bug.