This question refers to my previous question: clang does not compile my code, but g++ does. From my research, the issue at stake boils down to linkage, does the static variable data have linkage in the sample below (it compiles with g++-4.8.1)? How come it has linkage (I would not otherwise be able to instantiate with a non-type template parameter)?
template <int const* ptr>
void foo()
{
}
typedef void (*func_type)();
template <int = 0>
void run_me()
{
static int data;
func_type const f1 = foo<&data>;
// auto f2 = foo<&data>; // doesn't work with gcc
// foo<&data>(); // doesn't work with gcc
}
int main(int, char*[])
{
run_me();
return 0;
}
Obligatory quote from the standard:
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 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
...
Surely a static variable declared in a function (whether or not it is a template function) has no linkage.
§3.5 para. 8: "except as noted, a name declared at block scope (3.3.3) has no linkage"
The only exceptions listed in that clause, as far as I can see, are provided in para. 6: "The name of a function declared in block scope and the name of a variable declared by a block scope extern declaration have linkage."
However, it's possible that 14.3.2 might be loosened at some point.
Daniel Krügler submitted DR 1451 on 2012-02-01:
According to 14.3.2 [temp.arg.nontype] paragraph 1 bullet 3, only objects with linkage can be used to form non-type template arguments. Is this restriction still needed? It would be convenient to use block-scope objects as template arguments.
The DR was closed on the basis that it is an extension request and should be dealt with by the Evolution Working Group. It seems to have been included in n3413, "Allowing arbitrary literal types for non-type template parameters".
So it's certainly conceivable that one or more C++ compilers might choose to implement a looser restriction on non-type template parameters.
Related
I encountered the following problem by compiling the following example:
template <int N>
class Matrix {
public:
template <int Idx>
int head() {
return Idx;
}
};
template <typename T>
class Test {
static constexpr int RayDim = 3;
public:
int func() const {
Matrix<RayDim> yF;
return yF.head<1>();
// ^ is template keyword required here?
}
};
struct Empty {};
void test() {
Test<Empty> t;
}
Link to Compiler Explorer:
https://godbolt.org/z/js4XaP
The code compiles with GCC 9.2 and MSVC 19.22 but not with clang 9.0.0. Clang states that a template keyword is required. If static constexpr int RayDim = 3; is moved into int func() const clang accepts it.
As stated as a comment in the code block, is the template keyword required for yF.head<1>()?
The template keyword should not be required here, so clang is incorrect to reject the program.
All C++ Standard section and paragraph numbers and quotes below are the same for C++17 draft N4659 and the current linked C++20 draft.
The requirement for template after a . or -> or :: token when naming a member template is in [temp.names]/4. The paragraph first lists cases where the keyword is not allowed, then cases where it is optional and doesn't make a difference, then:
In all other contexts, when naming a template specialization of a member of an unknown specialization ([temp.dep.type]), the member template name shall be prefixed by the keyword template.
A "member of an unknown specialization" is a member of a dependent type which is not "the current instantiation". So the question is whether Matrix<RayDim> is a dependent type. For that, we look at [temp.dep.type]/9:
A type is dependent if it is
a template parameter,
a member of an unknown specialization,
a nested class or enumeration that is a dependent member of the current instantiation,
a cv-qualified type where the cv-unqualified type is dependent,
a compound type constructed from any dependent type,
an array type whose element type is dependent or whose bound (if any) is value-dependent,
a function type whose exception specification is value-dependent,
a simple-template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack expansion, or
denoted by decltype(expression), where expression is type-dependent.
Matrix<RayDim> is clearly not a template parameter, any kind of member, cv-qualified, an array type, a function type, or specified by decltype. It is a compound type, but it uses only a template-name and an expression, so is not constructed from any other type.
That leaves the simple-template-id case. The template name Matrix is not a template parameter. The template argument RayDim is an expression, so now to see if it is type-dependent or value-dependent.
"Type-dependent" is defined in [temp.dep.expr]. Only paragraph 3 can apply to a lone identifier like RayDim:
An id-expression is type-dependent if it contains
an identifier associated by name lookup with one or more declarations declared with a dependent type,
an identifier associated by name lookup with a non-type template-parameter declared with a type that contains a placeholder type,
an identifier associated by name lookup with a variable declared with a type that contains a placeholder type ([dcl.spec.auto]) where the initializer is type-dependent,
an identifier associated by name lookup with one or more declarations of member functions of the current instantiation declared with a return type that contains a placeholder type,
an identifier associated by name lookup with a structured binding declaration whose brace-or-equal-initializer is type-dependent,
the identifier __func__ ([dcl.fct.def.general]), where any enclosing function is a template, a member of a class template, or a generic lambda,
a template-id that is dependent,
a conversion-function-id that specifies a dependent type, or
a nested-name-specifier or a qualified-id that names a member of an unknown specialization;
or if it names a dependent member of the current instantiation that is a static data member of type "array of unknown bound of T" for some T ([temp.static]).
RayDim certainly does not contain any __func__, template-id, conversion-function-id, nested-name-specifier, or qualified-id. Name lookup finds the class template's static member declaration. That declaration of RayDim is certainly not a template-parameter, a member function, or a structured binding declaration, and its type const int is certainly not a dependent type or array type and does not contain a placeholder type. So RayDim is not type-dependent.
"Value-dependent" is defined in [temp.dep.constexpr]. The only cases that can apply to a lone identifier like RayDim are in paragraph 2:
An id-expression is value-dependent if:
it is type-dependent,
it is the name of a non-type template parameter,
it names a static data member that is a dependent member of the current instantiation and is not initialized in a member-declarator,
it names a static member function that is a dependent member of the current instantiation, or
it is a constant with literal type and is initialized with an expression that is value-dependent.
From above, RayDim is not type-dependent. It is certainly not a template parameter or a member function. It is a static data member and dependent member of the current instantiation, but it is initialized in the member-declarator. That is, the "= 3" appears inside the class definition, not in a separate member definition. It is a constant with literal type, but its initializer 3 is not value-dependent.
So RayDim is not value-dependent or type-dependent. Therefore Matrix<RayDim> is not a dependent type, yF.head is not a member of an unknown instantiation, and the template keyword before head is optional, not required. (It is permitted since it's not in a "type-only context" and head does in fact name a member template.)
Disclaimer
this is not an answer, but rather a long comment
My language-lawyer skills are too low to fully understand the standard but here are a few things I discovered from experimenting with the code. Everything that follows is based on my (far from perfect) understanding of the matter and probably needs some reviews.
Investigation
First off, I went to a fully defined standard version (C++17) so we operate on a well defined implementation.
Looking at this code it seems like MSVC still has some problems (with its lookup, I guess?) when it comes to template instantiation and redefinition. I wouldn't trust MSVC that much in our scenario.
That beeing said, lets think about why we could need the template keyword at
return yF.template head<1>();
Dependent names
Sometimes, inside templates, we have to help the compiler decide whether a name refers to
a value int T::x = 0,
a type struct T::x {};, or
a template template <typename U> T::foo<U>();
If we refer to a value, we do nothing. If we refer to a type, we have to use typename. And if we refer to a template we use template. More on that subject can be found here.
I don't understand the standard specification when it comes to the actual definition of a dependent name but here are some observations.
Observations
Lets take a look at the reference code
template <int N>
struct Matrix
{
template <int Idx>
int head() { return Idx; }
};
template <typename T>
struct Test
{
static constexpr int RayDim = 3;
int func() const
{
Matrix<RayDim> yF;
return yF.head<1>(); // clang complains, gcc and msvc are ok
}
};
struct Empty {};
int test()
{
Test<Empty> t;
return t.func();
}
Usually RayDim should be a dependent name (because it's inside the template Test) which would cause Matrix<RayDim> to be a dependent name aswell. For now, lets assume that Matrix<RayDim> actually is a dependent name. This makes Matrix<RayDim>::head a dependent name aswell. Since Matrix<RayDim>::head is a templated function it is a template in itself and the rules of dependent names from above apply, requiring us to use the template keyword. This is what clang is complaining about.
However, since RayDim is defined inside Test and func is also defined inside the same template and not a templated function in itself, I don't think RayDim actually is a dependent name in the context of func. Furthermore, RayDim doesn't rely on the template arguments of Test. In this case, Matrix<RayDim> and Matrix<RayDim>::head respectively, would become non-dependent names, which allows us to omit the template keyword. This is why gcc (and msvc) compile.
If we were to template RayDim aswell, like here
template <typename>
static constexpr int RayDim = 3;
gcc would treat it as a dependent name aswell (which is correct, since there might be a template specialization later so we don't know at that point). Meanwhile, msvc happily accepts everything we throw at it.
Conclusion
It seems like it's boiling down to whether RayDim is a dependent name in the context of Test<T>::func or not. Clang thinks it is, gcc doesn't. From some more test it looks like msvc sides with clang on this one. But it's also kinda doing it's own thing, so who knows?
I would side with gcc here as I see no possible way of RayDim becoming dependent at the point where func is instantiated.
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 type Bar (ie, main()). However, this is not correct. This is because the definition of a name with external linkage is described as:
When a name has external linkage, the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.
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 that foo<Bar> should have external linkage.
Thus, from C++.11 §14.3.2 Template non-type arguments ¶1:
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 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; ...
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):
Names not covered by these rules have no linkage. Moreover, except as noted, a name declared at block scope (3.3.3) has no linkage.
Same section goes on to say:
A type without linkage shall not be used as the type of a variable or function with external linkage unless
the entity has C language linkage (7.5), or
the entity is declared within an unnamed namespace (7.3.1), or
the entity is not odr-used (3.2) or is defined in the same translation unit.
And, as a matter of fact, Clang will allow this:
namespace
{
template<void (*FUNC_PTR)(void)>
struct Func {};
template<typename T>
void foo() {}
}
int main() {
struct Bar {}; // function-local type
Func<foo<Bar>> x;
}
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.
When answering this question, I tried the following code with gcc (code compiled) and clang (code rejected):
typedef long (*func)(int);
long function(int) { return 42; }
struct Test
{
static constexpr func f = &function;
};
template<func c>
struct Call
{
static void f()
{
c(0);
}
};
int main()
{
Call<Test::f>::f();
}
I am not sure which compiler is right, although I think the constexpr initialization of Test::f is ok. The error clang outputs is:
error: non-type template argument for template parameter of pointer type 'func'
(aka 'long (*)(int)') must have its address taken
Which compiler is right ?
If clang is right, why , and what does this error really means ?
EDIT: for the "why", see DyP's question.
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:
[...]
— 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; [...]
(n3485, emphasis mine)
I don't know exactly why it's been limited, but I think it might be related to the fact that the function address is not available at compile time (there might be a substitute for template instantiation purposes).
Edit: Enhanced answer due to a follow-up question (comment) of Synxis
constexpr func = &function;
^ this is well-formed; you can use the address of a function to initialize a constexpr object.
The problem is that it's explicitly forbidden to use pointers as non-type template arguments other than of the form &identifier:
using My_Call = Call < &function >; // fine
constexpr func mypointer = &function; // fine
using My_Ind_Call = Call < func >; // forbidden, argument not of form `&id`
ISO 98/03 standard (section 14.3.1) seems to forbid using a type with internal linkage as a template parameter. (See example below.) The C++11 standard does not.
G++ - using the old standard - is allowing it.
Am I misreading the 03 standard, or is g++ just letting this slide?
namespace
{
struct hidden { };
}
template<typename T>
struct S
{
T t;
};
int main()
{
S<hidden> s;
return 0;
}
You're correct that C++03 doesn't allow using a type with internal linkage as a template type parameter, while C++11 does.
I seem to recall, however, that definitions inside the anonymous namespace still have external linkage.
Yup, section 3.5 [basic.link] says
A name having namespace scope (3.3.5) has internal linkage if it is the name of
an object, reference, function or function template that is explicitly declared static or,
an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage; or
a data member of an anonymous union.
A name having namespace scope has external linkage if it is the name of
an object or reference, unless it has internal linkage; or
a function, unless it has internal linkage; or
a named class (clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (7.1.3); or
a named enumeration (7.2), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (7.1.3); or
an enumerator belonging to an enumeration with external linkage; or
a template, unless it is a function template that has internal linkage (clause 14); or
a namespace (7.3), unless it is declared within an unnamed namespace.
You have a named class at namespace scope, it has external linkage.
And the footnote on the bottom of page 115 of ISO/IEC 14882:2003 clarifies:
Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.
If you have another version, try looking in section 7.3.1.1 [namespace.unnamed]
That's not a valid example of the rule. The hidden class in your example has external linkage. (It has a compiler-generated unique name such that nothing outside the current translation unit can actually link with it, but it's still external.)
The standard gives an example of a local type:
template <class T> class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X<S> x3; // error: local type used as template-argument
X<S*> x4; // error: pointer to local type used as template-argument
}
According to the C++ Standard, function parameter's name is parsed by a declarator-id, and a declarator-id can also be a qualified name. That means, the following code is perfectly valid (if I've understood the relevant sections from the Standard correctly):
template<class T>
struct Sample
{
int fun(int T::count); //T::count is qualified variable name
};
My question basically is, why would anyone write such code? In what situations, the use of qualified name (in function parameter-list) can be advantageous?
EDIT:
It seems I understood the sections incorrectly. Instead of the above code, we can probably write the following code (as per the C++ standard):
template<class T>
struct sample
{
void fun(int arr[T::count]);
};
gcc-4.3.4 compiles it perfectly. But then, I'm not totally satisfied, because T::count is not a parameter anymore (I guess).
It's invalid. The syntax allows arbitrary declarators, but 8.3.5p8 says
An identifier can optionally be
provided as a parameter name; if
present in a function definition
(8.4), it names a parameter (sometimes
called “formal argument”)
Edit Another quote which syntactically constraints declarators (8.3p1, [dcl.meaning]):
Each declarator contains exactly one
declarator-id; it names the identifier
that is declared. The id-expression of
a declarator-id shall be a simple
identifier except for the declaration
of some special functions (12.3, 12.4,
13.5) and for the declaration of template specializations or partial
specializations (14.7). A declarator-id
shall not be qualified except for the
definition of a member function (9.3)
or static data member (9.4) or nested
class (9.7) outside of its class, the
definition or explicit instantiation
of a function, variable or class
member of a namespace outside of its
namespace, or the definition of a
previously declared explicit
specialization outside of its
namespace, or the declaration of a
friend function that is a member of
another class or namespace (11.4).
So in a parameter declaration, you must not use qualified names.
Edit: In the edited form, the function parameter type decays to an int*, even before a test is being made whether T::count actually exists and is an integer constant. If you want an example where a qualified name in such a signature would do something meaningful, consider
template<class T>
struct sample
{
void fun(int S=T::count);
};
When fun gets called without parameter, the compiler needs to determine the default argument, which then fails if T does not have a count member, or that cannot be converted to int.
As far as I understand your code is ill formed because
$8.3/1 : When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers, and the member shall not have been introduced by a using-declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id. [Note: if the qualifier is the global ::scope resolution operator, the declarator-id refers to a name declared in the global namespace scope. ]
P.S: I am not 100% sure. Please correct me if I am wrong. :)
In what situations, the use of qualified name (in function parameter-list) can be advantageous?
Read Items 31 and 32 from Exceptional C++ by Herb Sutter. Both the items deal with Koenig lookup and the Interface principle.
It seems I understood the sections incorrectly. Instead of that code, we can probably write the following code (as per the C++ standard):
template<class T>
struct sample
{
void fun(int arr[T::count]);
};
gcc-4.3.4 compiles it perfectly. But then, I'm not totally satisfied, because T::count is not a parameter anymore (I guess).