The following code compiles on GCC (doesn't even require a recent version), but it fails on clang 3.4:
template <int N>
struct T_unsigned {
typedef typename T_unsigned<N>::Type Type;
};
template <> struct T_unsigned<8> {
typedef unsigned char Type;
};
Using the above definition of T_unsigned, GCC allows you to use "T_unsigned<8>::Type" instead of "unsigned char". When I try to compile this using clang 3.4, I get:
test.cpp:3:41: error: no type named 'Type' in 'T_unsigned<N>'
typedef typename T_unsigned<N>::Type Type;
~~~~~~~~~~~~~~~~~~~~~~~~^~~~
1 error generated.
Is clang failing to compile correct C++11 code, or is this code doing something non-standard that GCC happens to support?
In your general case T_unsigned<N>, we have:
A name is a member of the current instantiation if it is
[...]
A qualified-id in which the nested-name-specifier refers to the current instantiation.
[ Example:
template <class T> class A {
static const int i = 5;
int n1[i]; // i refers to a member of the current instantiation
int n2[A::i]; // A::i refers to a member of the current instantiation
int n3[A<T>::i]; // A<T>::i refers to a member of the current instantiation
int f();
};
Within T_unsigned<N>, T_unsigned<N> is just another name for itself. So basically you have something like:
class Foo {
typedef Foo::Type Type;
};
and the "correct" error message should be approximately (http://ideone.com/FvJHBF):
prog.cpp:2:17: error: ‘Type’ in ‘class Foo’ does not name a type
typedef Foo::Type Type;
^
However, you write that you have problems with using your specialization T_unsigned<8>, which is seemingly not found by clang.
Your testcase is not too exhaustive, so my answer depends on an if-statement:
If at the point of instantiation, your specialization for N=8 is visible, than clang is doubly wrong. If not, gcc and clang should both fail, but with aforementioned error message (though the error message itself is in no way defined by the standard, so this is a tool's should, not a standard's).
The name that you use as the typedef is not dependent (see the clauses that define dependent names) and the namelookup in definition context at that place will not find a declaration. That in itself is an error already.
But since there is no declaration for the name yet, the name is also not a member of a class that is the current instantiation or a base class thereof. Therefore the name is not a member of the current instantiation and therefore we have another reason to reject it by a rule that says that if the qualifier is the current instantiation, the name either must refer to a member of that instantiation, or to a member of an unknown specialization (which would be the case if the class had dependent base classes).
Note the notion of "current instantiation": the meaning of the qualifier is fixed to refer to the result of instantiating the surrounding template, we don't wait for resolving the template arguments. Hence the term is not called "current specialization", since we know that it refers to an instantiated specialization, as opposed to a later declared explicit specialization.
The thing is different for C++03 I think. The name will be dependent and the template definition is harder to deem illformed with the rules available. The illformed, no diagnostic required, behavior will however happen when you try to instantiate the template before providing the explicit specialization. I think such code refering to itself makes no sense because you never are able to actually instantiate the template validly (and there is a rule that allows rejecting a template straight away in such cases).
Related
This issue is based on section C++ reference : dependent name - The template disambiguator for dependent name.
I have understood when invoking the template member function in a template class, the keyword template is necessary to make the compiler know the following bracket is used for indicating template argument.just like the used example in this section.
template<typename T>
struct S {
template<typename U> void foo(){}
};
template<typename T>
void bar()
{
S<T> s;
s.foo<T>(); // error: < parsed as less than operator
s.template foo<T>(); // OK
}
However, in the consequent part it describes when a template name appears in a member access expression (after -> or after .), the disambiguator is unnecessary if there is a template with the same name found by ordinary lookup in the context of the expression..
Then it comes with the following code. Comparing with previous example it defines set function whose name exists in standard library as well. At the meanwhile, using std::set is set up to make set template visible in template function.
In this condition, even if keyword template is not provided it still works well.
#include <set>
using std::set; // makes 'set' visible to lookup from bar
template<typename T>
struct S {
template<typename U> void set(){}
};
template<typename T>
void bar()
{
S<T> s;
s.set<T>(); // not an error if ::set is visible:
// (and since C++11, this is well-formed)
s.template set<T>(); // works with and without ::set
}
Based on my understanding, I tried my own version
#include <iostream>
template <typename T>
struct S{
template <typename U> void func(){
std::cout << "In S::func\n";
}
};
// In order to make member template function is visible in function test,
// defining a global template function **func** whose name is same with one
// member template function in struct S.
template <typename M>
void func(){
std::cout << "from ordinary func\n";
}
template <typename M>
void test(){
S<M> s;
func<M>(); // test func template function is visible in test function
s.func<M>();
}
int main(){
test<int>();
}
The detail error message is listed as follows
[17:17:50][ryu#C++_test]$ g++ -g typename2.cpp
typename2.cpp:61:7: error: use 'template' keyword to treat 'func' as a dependent
template name
s.func<M>();
^
template
1 error generated.
Any advice is appreciated on how to make my own code works well without keyword template.
Short version
Don't rely on this. Use the template keyword as you're supposed to, don't try such an obscure hack only to avoid a few keystrokes. Your code should definitely not compile according to the standard, and the example you quoted from cppreference.com may soon become explicitly disallowed as well (I don't think it was valid in the first place). GCC and Clang yield different results for both these examples. Even if they compile today, they may fail tomorrow in the next compiler version.
Long version
Regarding the example from cppreference.com, let's first note that Clang 3.6.0 compiles the code, but GCC 5.1.0 rejects both s.set<T>() and s.template set<T>() with the error invalid use of 'class std::set<T>'. I don't think either of the two compilers does the right thing here according to the standard, but, intuitively, GCC's error message makes a lot of sense: what would be the meaning of s.set<T>() with set<T> being a class template specialization?
With your code, it's the other way around: Clang rejects it (the error message quoted in the question seems to be actually from Clang) and GCC compiles it.
The examples rely on paragraph [3.4.5p1] in the standard (emphasis mine in all quotes):
In a class member access expression (5.2.5), if the . or -> token is
immediately followed by an identifier followed by a <, the identifier
must be looked up to determine whether the < is the beginning of a
template argument list (14.2) or a less-than operator. The identifier
is first looked up in the class of the object expression. If the
identifier is not found, it is then looked up in the context of the
entire postfix-expression and shall name a class template.
The class template part is the reason for your code being rejected by Clang (your func is a function template). Function templates were removed from there as the resolution of defect 141, included in C++11. It's worth mentioning a comment in the defect report:
There do not seem to be any circumstances in which use of a non-member
template function would be well-formed as the id-expression of a class
member access expression.
I think this says something about the intent of this lookup rule: it's supposed to find constructs that are well formed; it's not intended to just make the parser happy about those <> with some temporary match that will later be replaced by something else with entirely different semantics.
Even with the special lookup rule above, I'm not sure the standard allows you to omit the template in such cases. Paragraph [14.2p4] says:
When the name of a member template specialization appears after . or
-> in a postfix-expression or after a nested-name-specifier in a qualified-id, and the object expression of the postfix-expression is
type-dependent or the nested-name-specifier in the qualified-id refers
to a dependent type, but the name is not a member of the current
instantiation (14.6.2.1), the member template name must be prefixed by
the keyword template. Otherwise the name is assumed to name a
non-template.
Both member templates set and func in the two examples satisfy the conditions in there, respectively. As you can see, there's no mention of an exception to this rule.
Or, to put it another way, if you want set to be resolved as the name for the member template, it has to have template in front of it. If it doesn't, it can be resolved as the namespace-scope set, but then the set name itself is no longer a name dependent on template parameters (set<T> is still dependent, but set itself is not). And then we get to [14.6p10], which says:
If a name does not depend on a template-parameter (as defined in
14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template
definition; the name is bound to the declaration (or declarations)
found at that point and this binding is not affected by declarations
that are visible at the point of instantiation.
Once bound, it's carved in stone and the later switch to the member template is not valid, which makes the cppreference.com example incorrect.
Moreover, there's an open issue regarding the applicability of the lookup rule from [3.4.5p1] to such examples - issue 1835. Quoting a note in there:
One possibility might be to limit the lookup to the class of the
object expression when the object expression is dependent.
The issue is in drafting status, which means informal consensus has been reached in the working group. Exactly what that consensus was remains to be seen, but I'd say there's a good chance that something will change. Relying on such code doesn't seem like a good idea.
The quoted paragraphs have remained unchanged since C++11 up to the current working draft (N4431).
I have a problem with this code snippet:
template <typename T>
struct S
{
static int a;
};
template <typename T>
decltype(S<T>::a) S<T>::a;
clang-3.4 says:
s.cpp:8:25: error: redefinition of 'a' with a different type: 'decltype(S<T>::a)' vs 'int'
decltype(S<T>::a) S<T>::a;
^
s.cpp:4:14: note: previous definition is here
static int a;
^
1 error generated.
But gcc-4.8.2 accepts. Which of the compilers is right? Should I avoid such code in the future?
Clang is demanding that the definition match the declaration at template definition time, whereas GCC and others defer matching until instantiation time (which never even happens for your example).
Clang accepts this:
#include <type_traits>
template <typename T>
struct S
{
static int a;
};
template <typename T>
typename std::enable_if< true, int >::type S<T>::a; // Resolves before instantiation
but rejects this small change:
template <typename T>
typename std::enable_if< std::is_same< T, T >::value, int >::type S<T>::a;
I cannot recall where the standard dictates when object declaration matching occurs, but I suspect that Clang is within its rights to reject the code. The intent of the standard, if I recall correctly, is that each declaration matches exactly one definition, and that mapping may be determined before instantiation time.
With the looser rule that GCC is apparently applying, you could have two member declarations and two definitions, but each definition may finalize either of the declarations depending on the template parameters.
The code which GCC and MSVC are accepting is ill-formed, no diagnosis required… pending finding the actual standardese buried somewhere in §3 [basic], §7 [dcl.dcl], §8 [dcl.decl], §14 [temp], or maybe somewhere else.
I still cannot find what rule matches object definitions to preceding declarations, but §14.4/2 dictates that decltype(…) cannot be the equivalent (I assume in the declarative sense) to int.
If an expression e involves a template parameter, decltype(e)
denotes a unique dependent type. Two such decltype-specifiers refer
to the same type only if their expressions are equivalent (14.5.6.1).
[Note: however, it may be aliased, e.g., by a typedef-name. — end
note ]
I'm pretty sure that equivalence, not mere aliasing, is necessary for the definition to match the declaration. §14.5.6.1 delves pretty deep into this territory, except it is specifically discussing function signatures.
I think Clang might be right in rejecting this. 14.2p2 says about decltype(e)
If an expression e involves a template parameter, decltype(e) denotes a unique dependent type.
In DR #2, the discussion trace says
My opinion (which I think matches several posted on the reflector recently) is that the out-of-class definition must match the declaration in the template.
...
In general, if you can match the declarations up using only information from the template, then the declaration is valid.
I think it still matches if one of them uses a typedef (as demonstrated in the DR), because S<T>::type is a member of the current instantiation and the type aliased can be looked up directly. But a decltype(e), as specified above, will always denote a unique type (during template parse time) except with respect to another decltype(e) that specifies an equivalent expression.
Why did I say might? Because of 14.6p8
No diagnostic shall be issued for a template for which a valid specialization can be generated.
One could read this as saying the type equivalence check is simply delayed till after instantiation. This, however, would contradict the discussion trace in the DR I think, because they say "if you can match the declarations up using only information from the template, then the declaration is valid" (and I assume the author of this statement meant to be exhaustive about the situations when the declaration is valid).
For me clang is broken here.
All combinations with decltype will fail. Without decltype it works.
template <typename T>
struct S
{
static int a;
using type = decltype( a );
typedef decltype( a ) type2;
};
template <typename T>
1) decltype(S<T>::a) S<T>::a;
2) int S<T>::a;
3) typename S<T>::type S<T>::a;
4) typename S<T>::type2 S<T>::a;
1 gcc works, clang fails
2 gcc + clang works
3 gcc works, clang fails
4 gcc works, clang fails
I did some more tries to work around the problem, but could not have any success.
There are some more discussions on that kind of problems:
C++ Static member initalization (template fun inside)
Edit:
I found that this topic is simply "not resolved" in the standard until now and clang did not implemented it:
Take a look at:
http://clang.llvm.org/cxx_dr_status.html ( point 205 )
I hope that I did not misunderstood the page. Feel free to correct my interpretation.
In the following example, A has a member typedef Instantiate which causes the instantiation of B<A>.
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After After; // error: no type named 'After' in 'A<int>'
};
template<typename T>
struct A
{
typedef int Before;
typedef typename B<A>::After Instantiate;
typedef int After;
};
template struct A<int>; // instantiate A<int>
All the compilers I've tried report that, while A::Before is visible, A::After is not. Is this behaviour compliant with the standard? If so, where does the standard specify which names in A should be visible during instantiation of B<A>?
If dependent names are "looked up at the point of the template instantiation", what does this mean in the scenario of a name qualified by a template parameter such as T::After?
EDIT: Note that the same behaviour occurs when A is not a template:
template<typename T>
struct B
{
typedef typename T::Before Before; // ok
typedef typename T::After After; // error: no type named 'After' in 'A'
};
struct A
{
typedef int Before;
typedef B<A>::After Instantiate;
typedef int After;
};
.. and G++ accepts the following, but Clang does not:
template<typename T>
struct B
{
static const int value = 0;
static const int i = T::value; // clang error: not a constant expression
};
struct A
{
static const int value = B<A>::value;
};
EDIT: After some reading of the C++03 standard:
[temp.dep.type] A type is dependent if it is a template parameter
Therefore T is dependent.
[temp.res] When looking for the declaration of a name used in a template definition, the usual lookup rules are used for nondependent names. The lookup of names dependent on the template parameters is postponed until the actual template argument is known.
The lookup of T::After is therefore postponed until the argument for T is known.
[temp.inst] Unless a class template specialization has been explicitly instantiated ... the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type.
Therefore the declaration of A<int>::Instantiate requires the instantiation of B<A> (because it is used in a nested-name-specifier.)
A<int>::After is not visible at the point of declaration of A<int>::Instantiate, so the behaviour of the compiler makes sense - but I haven't seen anything in C++03 that explicitly describes this behaviour. The closest thing was this somewhat vague paragraph:
[temp.dep.res]
In resolving dependent names, names from the following sources are considered:
— Declarations that are visible at the point of definition of the template.
Whether typename T::Before is valid is not explicitly said by the spec. It is subject of a defect report (because the Standard can very reasonably be read to forbid it): http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#287 .
Whether typename T::After is invalid can also very reasonably be read to be true by the spec, and actually it makes quite a bit of sense (and aforementioned DR still keeps it ill-formed). Because you have an instantiation of a class A<Foo>, which references another class A<Bar> during a period where a member Baz has not yet been declared, and that makes a reference back to A<Foo>::Bar. That is ill-formed in the case of non-templates aswell (try to "forget" for a moment that you are dealing with templates: surely the lookup of B<A>::After is done after the A template was completely parsed, but not after the specific instantiation of it was completely created. And it is the instantiation of it that actually will do the reference!).
struct A {
typedef int Foo;
typedef A::Foo Bar; // valid
typedef A::Baz Lulz; // *not* valid
typedef int Baz;
};
T::Before and T::After are dependent names due to [temp.dep.type]/8 and /5.
Dependent names are looked up "at the point of the template instantiation (14.6.4.1) in both the context of the template definition and the context of the point of instantiation." [temp.dep]/1
I interpret this as: They're looked up when the template is instantiated. Where are they looked up? At the context of the template definition and the context of the point of instantiation.
[temp.dep.type]/7 On the other hand states:
If, for a given set of template arguments, a specialization of a template is instantiated that refers to a member of the current instantiation with a qualified-id or class member access expression, the name in the qualified-id or class member access expression is looked up in the template instantiation context.
[temp.point]/7 Defines the instantiation context as follows:
The instantiation context of an expression that depends on the template arguments is the set of declarations with external linkage declared prior to the point of instantiation of the template specialization in the same translation unit.
Therefore, we need to know what the point of instantiation is.
[temp.point]/4
For a class template specialization [...], if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the
enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template.
Although the injected class name A is arguably a context that depends (as a layman term) on the template parameters of A, the name A itself is not a dependent name. Correction by Johannes Schaub: It is a dependent name. See [temp.local]/1 and [temp.dep.type]/8 => A is a dependent type.
Therefore, this condition is not fulfilled, and B<A> should be instantiated before A<int>.
static_cast<the_template<int>*>(0) - does this instantiate the_template with type int?
The reason for asking is the following code, which will error at linking time with an undefined reference to check_error<char>(void*, long) with Clang and GCC 4.4.5, indicating that it does not instantiate the template. MSVC and GCC 4.5.1 however compile and link just fine, leading to the believe that it does instantiate the template. However, if you leave out the cast, MSVC and GCC (both 4.4.5 and 4.5.1) will error on check_error<char> only (the wanted behaviour), while Clang will error on both calls. Normally I believe Clang when it comes to conforming stuff, but I wonder:
Which compiler is correct and what does the standard say about it?
#include <type_traits>
template<class T>
void check_error(void*, long);
template<class T>
struct foo{
template<class U>
friend typename std::enable_if<
std::is_same<T,U>::value
>::type check_error(foo<T>*, int){}
};
template struct foo<int>;
int main()
{
check_error<int>(static_cast<foo<int>*>(0), 0);
check_error<char>(static_cast<foo<char>*>(0), 0);
}
It is not the cast that instantiates the class template specialization, but the function call, because the argument triggers ADL . The instantiation is done because the completeness of it may affect the semantics of the program.
That clang does not follow the spec here is known and a PR was sent by me some time ago. See http://llvm.org/bugs/show_bug.cgi?id=9440
n3242 §14.7.1/1
Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3),
the class template specialization is implicitly instantiated when the specialization is referenced in a context
that requires a completely-defined object type or when the completeness of the class type affects the semantics
of the program. The implicit instantiation of a class template specialization causes the implicit
instantiation of the declarations, but not of the definitions or default arguments, of the class member functions,
member classes, static data members and member templates; and it causes the implicit instantiation
of the definitions of member anonymous unions. Unless a member of a class template or a member template
has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated
when the specialization is referenced in a context that requires the member definition to exist; in
particular, the initialization (and any associated side-effects) of a static data member does not occur unless
the static data member is itself used in a way that requires the definition of the static data member to exist.
It seems to me that static_cast would require the instantiation of the declarations, but not of the definitions (as you are just dealing with pointers).
n3242 §14.6.5/1
Friend classes or functions can be declared within a class template. When a template is instantiated, the
names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.
I think that it should link, but maybe someone else can interpret better than I can.
Check out the following code (written just for fun)
namespace N
{
template<typename T>
struct K
{
};
}
template<typename T>
struct X
{
typename T::template K<T> *p; //should give error
//N::K<int> has no template member named `K`
};
int main()
{
X<N::K<int> > l;
}
The code gets compiled on g++(4.5.1) and Clang whereas Comeau and Intel C++ give (similar) errors.
The errors that I get on Comeau are :
"ComeauTest.c", line 13: error: class "N::K<int>" has no member "K"
typename T::template K<T> *p;
^
detected during instantiation of class "X<T> [with T=N::K<int>]" at
line 18
"ComeauTest.c", line 13: error: expected an identifier
typename T::template K<T> *p;
^
detected during instantiation of class "X<T> [with T=N::K<int>]" at
line 18
So my question is "Is the code sample ill-formed ?" According to me "Yes". Does that mean this is yet another bug in g++/Clang?
Why GCC and Clang think they are right
K, which is the injected class name, has a dual nature in the scope of K<int>. You can use it without template arguments. Then it refers to K<int> (to its own type).
It can be followed by a template argument list too. IMO it's reasonable to say that you need to prefix it with template because of the parser ambiguity with the < that follows. It then refers to the specified type that's determined by the template arguments.
So it can be treated as a member template and as a nested type, depending on whether it's followed by a template argument list. Of course, K is not really a member template. The dual nature of the injected class name seems to me more of a hack anyway, though.
The Standard has an example that reads like this:
template <class T> struct Base { };
template <class T> struct Derived: Base<int>, Base<char> {
typename Derived::Base b; // error: ambiguous
typename Derived::Base<double> d; // OK
};
One might be inclined to conclude from this that the intent is that you could leave off the template. The Standard says
For a template-name to be explicitly qualified by the template arguments, the name must be known to refer to a template.
I can't see how this wouldn't apply to T::K<T>. If T is a dependent type then you can just lean back because you can't know what K refers to when parsing it, so to make any sense of the code, you just have to be able to prefix it with template. Notice that n3225 has that example too, but it's not a defect there: You can officially leave off template if you lookup into the template's own scope in C++0x (it's called the "current instantiation").
So until now, Clang and GCC are fine.
Why Comeau is right
Just to make it even more complicated, we will have to consider the constructors of K<int>. There is a default constructor and a copy constructor implicitly declared. A name K<int>::K will refer to the constructor(s) of K<int> unless the name lookup used will ignore function (constructor) names. Will typename T::K ignore function names? 3.4.4/3 says about elaborated type specifiers, which typename ... is one of:
If the name is a qualified-id, the name is looked up according its qualifications, as described in 3.4.3, but ignoring any non-type names that have been declared.
However, a typename ... uses different lookup. 14.6/4 says
The usual qualified name lookup (3.4.3) is used to find the qualified-id even in the presence of typename.
The usual qualified lookup of 3.4.3 won't ignore non-type names, as illustrated by the example attached to 14.6/4. So, we will find the constructor(s) as specified by 3.4.3.1/1a (the additional twist that this only happens when non-types are not ignored was added by a later defect report, which all popular C++03 compilers implement though):
If the nested-name-specifier nominates a class C, and the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (clause 9), the name is instead considered to name the constructor of class C. Such a constructor name shall be used only in the declarator-id of a constructor definition that appears outside of the class definition.
So in the end, I think comeau is correct to diagnose this, because you try to put a template argument list onto a non-template and also violate the requirement quoted in the last part (you use the name elsewhere).
Let's change it by accessing the injected name by a derived class, so no constructor name translation occurs, and you really access the type so that you really can append the template arguments:
// just replace struct X with this:
template<typename T>
struct X
{
struct Derived : T { };
typename Derived::template K<T> *p;
};
Everything compiles now with comeau too! Notice I already did problem report to clang about this exact thing. See Incorrect constructor name resolution. BTW, if you declare a default constructor in K, you can see comeau give a better error message if you use T::K<int>
"ComeauTest.c", line 13: error: overloaded function "N::K<T>::K [with T=int]" is
not a template
typename T::template K<T> *p;