Topic: After dependent name lookup: Changing parse tree in context of a template-name?
Author: Nikolay Ivchenkov <tsoae@mail.ru>
Date: Wed, 7 Apr 2010 15:16:30 CST Raw View
On 7 Apr, 00:11, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:
> Comeau sees to parse the template body assuming that "T::Bar<1>(0)" is
> using op<, but then when dependent name lookup finishes, decides to take
> "T::Bar<1>" as a template-id. It looks to me that 14.2/3 can be interpreted
> in that manner. (I don't think that it intends to be interpreted that way,
> though and some committee member told me so too).
Probably, Comeau C++ performs trial parsing of a template definition
and then reparses the definition of the respective template
specialization considering template arguments and ignoring the rules
quoted in my previous message. On the first step it considers T::Bar
as an expression, but on the second step it wrongfully considers
T::Bar and T::Bar<1> as template and simple-type-specifier
respectively.
According to the rules (C++03 or N3092), we must use "template" and
"typename" keywords here:
struct Foo {
template <int>
struct Bar { Bar(int) {} };
};
template <class T>
void foo() {
typename T::template Bar < 1 > (0);
}
int main() {
foo<Foo>();
}
Otherwise the program is ill-formed, and the diagnostic is required.
Moreover, we must use "template" keyword even if template-id is not
formed:
struct Foo {
template <class T>
static void bar(T) { }
};
template <class T>
void foo() {
T::template bar(0); // "template" is necessary
}
int main() {
foo<Foo>();
}
Comeau C++ wrongfully rejects this code.
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: Nikolay Ivchenkov <tsoae@mail.ru>
Date: Mon, 5 Apr 2010 19:20:45 CST Raw View
On 23 Mar, 13:35, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:
> A question arose in a thread of comp.lang.c++.moderated whether the
> following is well-formed or ill-formed:
>
> struct Foo {
> template <int I>
> static void bar(char(*)[I]) { }
>
> };
>
> template <class T>
> void foo() {
> typedef char one[1];
> !(void(*)(one*))T::bar < -1 > (0);
>
> }
>
> int main(){
> foo<Foo>();
>
> }
>
> The comeau compiler (and apparently the intel compiler too) accepts that
> code, apparently treating "T::bar<-1>" as a template-id instead of an
> expression with two relational operators. So comeau/intel fails to compile
> because of SFINAE making "bar" non-viable. Other compilers compile this
> fine, because the cast deduces "I" to 1, and we end up comparing the
result
> converted to bool to "-1".
IMO, the behavior of Comeau C++ and these "other compilers" is wrong.
C++03 [temp.names]/4:
"When the name of a member template specialization appears after . or -
> in a postfix-expression, or after nested-name-specifier in a
qualified-id, and the postfix-expression or qualified-id explicitly
depends on a template-parameter (14.6.2), the member template name
must be prefixed by the keyword template."
C++03 [temp.res]/3:
"A qualified-id that refers to a type and in which the nested-name-
specifier depends on a template-parameter (14.6.2) shall be prefixed
by the keyword typename to indicate that the qualified-id denotes a
type, forming an elaborated-type-specifier (7.1.5.3)."
N3092 [temp.names]/4:
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 postfix-expression or qualified-id explicitly
depends on a template-parameter (14.6.2) but does not refer to a
member of the current instantiation (14.6.2.1), the member template
name must be prefixed by the keyword template.
N3092 [temp.res]/3:
"When a qualified-id is intended to refer to a type that is not a
member of the current instantiation (14.6.2.1) and its nested-name-
specifier depends on a template-parameter (14.6.2), it shall be
prefixed by the keyword typename, forming a typename-specifier."
Comeau C++ frequently ignores these restrictions:
struct Foo {
template <int>
struct Bar { Bar(int) {} };
};
template <class T>
void foo() {
T::Bar < 1 > (0);
}
int main() {
foo<Foo>(); // must be diagnosed
}
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Tue, 6 Apr 2010 14:11:02 CST Raw View
Nikolay Ivchenkov wrote:
> On 23 Mar, 13:35, "Johannes Schaub (litb)" <schaub-johan...@web.de>
> wrote:
>> A question arose in a thread of comp.lang.c++.moderated whether the
>> following is well-formed or ill-formed:
>>
>> struct Foo {
>> template <int I>
>> static void bar(char(*)[I]) { }
>>
>> };
>>
>> template <class T>
>> void foo() {
>> typedef char one[1];
>> !(void(*)(one*))T::bar < -1 > (0);
>>
>> }
>>
>> int main(){
>> foo<Foo>();
>>
>> }
>>
>> The comeau compiler (and apparently the intel compiler too) accepts that
>> code, apparently treating "T::bar<-1>" as a template-id instead of an
>> expression with two relational operators. So comeau/intel fails to
>> compile because of SFINAE making "bar" non-viable. Other compilers
>> compile this fine, because the cast deduces "I" to 1, and we end up
>> comparing the
> result
>> converted to bool to "-1".
>
> IMO, the behavior of Comeau C++ and these "other compilers" is wrong.
>
> C++03 [temp.names]/4:
> "When the name of a member template specialization appears after . or -
>> in a postfix-expression, or after nested-name-specifier in a
> qualified-id, and the postfix-expression or qualified-id explicitly
> depends on a template-parameter (14.6.2), the member template name
> must be prefixed by the keyword template."
>
> C++03 [temp.res]/3:
> "A qualified-id that refers to a type and in which the nested-name-
> specifier depends on a template-parameter (14.6.2) shall be prefixed
> by the keyword typename to indicate that the qualified-id denotes a
> type, forming an elaborated-type-specifier (7.1.5.3)."
>
> N3092 [temp.names]/4:
> 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 postfix-expression or qualified-id explicitly
> depends on a template-parameter (14.6.2) but does not refer to a
> member of the current instantiation (14.6.2.1), the member template
> name must be prefixed by the keyword template.
>
> N3092 [temp.res]/3:
> "When a qualified-id is intended to refer to a type that is not a
> member of the current instantiation (14.6.2.1) and its nested-name-
> specifier depends on a template-parameter (14.6.2), it shall be
> prefixed by the keyword typename, forming a typename-specifier."
>
> Comeau C++ frequently ignores these restrictions:
>
> struct Foo {
> template <int>
> struct Bar { Bar(int) {} };
> };
>
> template <class T>
> void foo() {
> T::Bar < 1 > (0);
> }
>
> int main() {
> foo<Foo>(); // must be diagnosed
> }
>
>
I'm wondering whether this is because of
14.2/3
"After name lookup (3.4) finds that a name is a template-name, if this name
is followed by a <, the < is always taken as the beginning of a template-
argument-list and never as a name followed by the less-than operator. "
? Comeau sees to parse the template body assuming that "T::Bar<1>(0)" is
using op<, but then when dependent name lookup finishes, decides to take
"T::Bar<1>" as a template-id. It looks to me that 14.2/3 can be interpreted
in that manner. (I don't think that it intends to be interpreted that way,
though and some committee member told me so too).
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Tue, 23 Mar 2010 03:35:32 CST Raw View
A question arose in a thread of comp.lang.c++.moderated whether the
following is well-formed or ill-formed:
struct Foo {
template <int I>
static void bar(char(*)[I]) { }
};
template <class T>
void foo() {
typedef char one[1];
!(void(*)(one*))T::bar < -1 > (0);
}
int main(){
foo<Foo>();
}
The comeau compiler (and apparently the intel compiler too) accepts that
code, apparently treating "T::bar<-1>" as a template-id instead of an
expression with two relational operators. So comeau/intel fails to compile
because of SFINAE making "bar" non-viable. Other compilers compile this
fine, because the cast deduces "I" to 1, and we end up comparing the result
converted to bool to "-1".
Why does comeau behave the way it behaves? Any EDG guys in here? Thanks!
--
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]