Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c++ > #86787 > unrolled thread
| Started by | "daniel...@gmail.com" <danielaparker@gmail.com> |
|---|---|
| First post | 2022-10-03 14:09 -0700 |
| Last post | 2022-10-08 11:18 -0700 |
| Articles | 10 — 6 participants |
Back to article view | Back to comp.lang.c++
Is this valid C++ code? "daniel...@gmail.com" <danielaparker@gmail.com> - 2022-10-03 14:09 -0700
Re: Is this valid C++ code? David LaRue <huey.dll@tampabay.rr.com> - 2022-10-03 23:52 +0000
Re: Is this valid C++ code? "daniel...@gmail.com" <danielaparker@gmail.com> - 2022-10-03 18:07 -0700
Re: Is this valid C++ code? "daniel...@gmail.com" <danielaparker@gmail.com> - 2022-10-03 18:42 -0700
Re: Is this valid C++ code? Juha Nieminen <nospam@thanks.invalid> - 2022-10-04 06:05 +0000
Re: Is this valid C++ code? Bo Persson <bo@bo-persson.se> - 2022-10-04 13:47 +0200
Re: Is this valid C++ code? "daniel...@gmail.com" <danielaparker@gmail.com> - 2022-10-04 05:22 -0700
Re: Is this valid C++ code? Manfred <noname@add.invalid> - 2022-10-05 02:54 +0200
Re: Is this valid C++ code? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-10-07 12:41 -0700
Re: Is this valid C++ code? Andrey Tarasevich <andreytarasevich@hotmail.com> - 2022-10-08 11:18 -0700
| From | "daniel...@gmail.com" <danielaparker@gmail.com> |
|---|---|
| Date | 2022-10-03 14:09 -0700 |
| Subject | Is this valid C++ code? |
| Message-ID | <bc46c146-abb5-4b16-b62d-324e049c7083n@googlegroups.com> |
Hello everyone,
Is the C++ code below valid?
#include <iostream>
#include <string_view>
#include <string>
template <class T, class Enable = void>
class Foo
{};
template <class T>
class Foo<T,typename std::enable_if<std::is_same<T,std::string>::value>::type>
{
public:
void f(std::string s)
{
Foo<std::string_view> foo; // (*)
foo.f(s);
}
};
template <class T>
class Foo<T, typename std::enable_if<std::is_same<T, std::string_view>::value>::type>
{
public:
void f(std::string_view s)
{
std::cout << s << "\n";
}
};
int main()
{
Foo<std::string> foo;
foo.f("Hello World");
}
LLVM (clang-cl) says "yes", and outputs "Hello World".
Visual Studio 2022 (v143) says "no", "'f': is not a member of 'Foo<std::basic_string_view<char,std::char_traits<char>>,void>", 17
at line (*)
Both compiled with C++17.
Thanks,
Daniel
[toc] | [next] | [standalone]
| From | David LaRue <huey.dll@tampabay.rr.com> |
|---|---|
| Date | 2022-10-03 23:52 +0000 |
| Message-ID | <XnsAF25CA3284913hueydlltampabayrrcom@46.165.242.75> |
| In reply to | #86787 |
"daniel...@gmail.com" <danielaparker@gmail.com> wrote in
news:bc46c146-abb5-4b16-b62d-324e049c7083n@googlegroups.com:
> Hello everyone,
>
> Is the C++ code below valid?
When asking such a question, you should specify the standard or compilers
that you are interested in using. As you see from the results below, one
compiler says it isn't valid and the other says it is valid. The
difference is likely in the standard that each implements as its
standard. Note that the applicable standard may be controlled by a
setting.
> #include <iostream>
> #include <string_view>
> #include <string>
>
> template <class T, class Enable = void>
> class Foo
> {};
>
> template <class T>
> class Foo<T,typename
> std::enable_if<std::is_same<T,std::string>::value>::type> {
> public:
>
> void f(std::string s)
> {
> Foo<std::string_view> foo; // (*)
> foo.f(s);
> }
> };
>
> template <class T>
> class Foo<T, typename std::enable_if<std::is_same<T,
> std::string_view>::value>::type> {
> public:
>
> void f(std::string_view s)
> {
> std::cout << s << "\n";
> }
> };
>
> int main()
> {
> Foo<std::string> foo;
> foo.f("Hello World");
> }
>
> LLVM (clang-cl) says "yes", and outputs "Hello World".
>
> Visual Studio 2022 (v143) says "no", "'f': is not a member of
> 'Foo<std::basic_string_view<char,std::char_traits<char>>,void>",
> 17 at line (*)
>
> Both compiled with C++17.
>
> Thanks,
> Daniel
>
[toc] | [prev] | [next] | [standalone]
| From | "daniel...@gmail.com" <danielaparker@gmail.com> |
|---|---|
| Date | 2022-10-03 18:07 -0700 |
| Message-ID | <fb857369-f722-4c85-b185-d576a4b7c32fn@googlegroups.com> |
| In reply to | #86788 |
On Monday, October 3, 2022 at 7:53:04 PM UTC-4, David LaRue wrote: > "daniel...@gmail.com" <daniel...@gmail.com> wrote in > news:bc46c146-abb5-4b16...@googlegroups.com: > > Hello everyone, > > > > Is the C++ code below valid? > When asking such a question, you should specify the standard or compilers > that you are interested in using. As you see from the results below, one > compiler says it isn't valid and the other says it is valid. The > difference is likely in the standard that each implements as its > standard. Note that the applicable standard may be controlled by a > setting. I'm interested in responses about whether the posted code is valid C++ code or not for standards C++ 11 or greater. I'm not interested in whether it "works" for one compiler or another, only whether it's valid C++ code according to the standard. Thanks, Daniel
[toc] | [prev] | [next] | [standalone]
| From | "daniel...@gmail.com" <danielaparker@gmail.com> |
|---|---|
| Date | 2022-10-03 18:42 -0700 |
| Message-ID | <e3c311c4-f2f1-4cb4-8ee2-07526ce3a870n@googlegroups.com> |
| In reply to | #86789 |
On Monday, October 3, 2022 at 9:07:10 PM UTC-4, daniel...@gmail.com wrote: > I'm interested in responses about whether the posted code is valid > C++ code or not for standards C++ 11 or greater. I'm not interested > in whether it "works" for one compiler or another, only whether it's > valid C++ code according to the standard. > Or rather, since I used std:string_view in the example code, for C++ 17 or later :-)
[toc] | [prev] | [next] | [standalone]
| From | Juha Nieminen <nospam@thanks.invalid> |
|---|---|
| Date | 2022-10-04 06:05 +0000 |
| Message-ID | <thgifm$174c$2@gioia.aioe.org> |
| In reply to | #86788 |
David LaRue <huey.dll@tampabay.rr.com> wrote: > When asking such a question, you should specify the standard or compilers > that you are interested in using. But he did: >> Both compiled with C++17.
[toc] | [prev] | [next] | [standalone]
| From | Bo Persson <bo@bo-persson.se> |
|---|---|
| Date | 2022-10-04 13:47 +0200 |
| Message-ID | <jq2kr7Ft790U1@mid.individual.net> |
| In reply to | #86787 |
On 2022-10-03 at 23:09, daniel...@gmail.com wrote:
> Hello everyone,
>
> Is the C++ code below valid?
>
> #include <iostream>
> #include <string_view>
> #include <string>
>
> template <class T, class Enable = void>
> class Foo
> {};
>
> template <class T>
> class Foo<T,typename std::enable_if<std::is_same<T,std::string>::value>::type>
> {
> public:
>
> void f(std::string s)
> {
> Foo<std::string_view> foo; // (*)
> foo.f(s);
> }
> };
>
> template <class T>
> class Foo<T, typename std::enable_if<std::is_same<T, std::string_view>::value>::type>
> {
> public:
>
> void f(std::string_view s)
> {
> std::cout << s << "\n";
> }
> };
>
> int main()
> {
> Foo<std::string> foo;
> foo.f("Hello World");
> }
>
> LLVM (clang-cl) says "yes", and outputs "Hello World".
>
> Visual Studio 2022 (v143) says "no", "'f': is not a member of 'Foo<std::basic_string_view<char,std::char_traits<char>>,void>", 17
> at line (*)
>
> Both compiled with C++17.
>
Seems like g++ (v12.2) agrees with VC++, and also points out the problem
that the specialization is defined after its first use.
My (non-language-lawyer) interpretation is that since f and its local
foo don't depend on the template parameter T, they should be looked up
immediately, and not at the point of instantiation.
[toc] | [prev] | [next] | [standalone]
| From | "daniel...@gmail.com" <danielaparker@gmail.com> |
|---|---|
| Date | 2022-10-04 05:22 -0700 |
| Message-ID | <40c751c7-806c-4921-a029-a355b0568671n@googlegroups.com> |
| In reply to | #86793 |
On Tuesday, October 4, 2022 at 7:48:09 AM UTC-4, Bo Persson wrote:
> On 2022-10-03 at 23:09, daniel...@gmail.com wrote:
> > Hello everyone,
> >
> > Is the C++ code below valid?
> >
> > #include <iostream>
> > #include <string_view>
> > #include <string>
> >
> > template <class T, class Enable = void>
> > class Foo
> > {};
> >
> > template <class T>
> > class Foo<T,typename std::enable_if<std::is_same<T,std::string>::value>::type>
> > {
> > public:
> >
> > void f(std::string s)
> > {
> > Foo<std::string_view> foo; // (*)
> > foo.f(s);
> > }
> > };
> >
> > template <class T>
> > class Foo<T, typename std::enable_if<std::is_same<T, std::string_view>::value>::type>
> > {
> > public:
> >
> > void f(std::string_view s)
> > {
> > std::cout << s << "\n";
> > }
> > };
> >
> > int main()
> > {
> > Foo<std::string> foo;
> > foo.f("Hello World");
> > }
> >
> > LLVM (clang-cl) says "yes", and outputs "Hello World".
> >
> > Visual Studio 2022 (v143) says "no", "'f': is not a member of 'Foo<std::basic_string_view<char,std::char_traits<char>>,void>", 17
> > at line (*)
> >
> > Both compiled with C++17.
> >
> Seems like g++ (v12.2) agrees with VC++, and also points out the problem
> that the specialization is defined after its first use.
>
> My (non-language-lawyer) interpretation is that since f and its local
> foo don't depend on the template parameter T, they should be looked up
> immediately, and not at the point of instantiation.
Thanks!
Daniel
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@add.invalid> |
|---|---|
| Date | 2022-10-05 02:54 +0200 |
| Message-ID | <thikk1$4vd$1@gioia.aioe.org> |
| In reply to | #86793 |
On 10/4/2022 1:47 PM, Bo Persson wrote:
> On 2022-10-03 at 23:09, daniel...@gmail.com wrote:
>> Hello everyone,
>>
>> Is the C++ code below valid?
>>
>> #include <iostream>
>> #include <string_view>
>> #include <string>
>>
>> template <class T, class Enable = void>
>> class Foo
>> {};
>>
>> template <class T>
>> class Foo<T,typename
>> std::enable_if<std::is_same<T,std::string>::value>::type>
>> {
>> public:
>> void f(std::string s)
>> {
>> Foo<std::string_view> foo; // (*)
>> foo.f(s);
>> }
>> };
>>
>> template <class T>
>> class Foo<T, typename std::enable_if<std::is_same<T,
>> std::string_view>::value>::type>
>> {
>> public:
>> void f(std::string_view s)
>> {
>> std::cout << s << "\n";
>> }
>> };
>>
>> int main()
>> {
>> Foo<std::string> foo;
>> foo.f("Hello World");
>> }
>>
>> LLVM (clang-cl) says "yes", and outputs "Hello World".
>>
>> Visual Studio 2022 (v143) says "no", "'f': is not a member of
>> 'Foo<std::basic_string_view<char,std::char_traits<char>>,void>", 17
>> at line (*)
>>
>> Both compiled with C++17.
>>
>
> Seems like g++ (v12.2) agrees with VC++, and also points out the problem
> that the specialization is defined after its first use.
>
> My (non-language-lawyer) interpretation is that since f and its local
> foo don't depend on the template parameter T, they should be looked up
> immediately, and not at the point of instantiation.
>
>
A good example of when someone's question, and its answer, are useful
for someone else too.
Thanks.
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-10-07 12:41 -0700 |
| Message-ID | <thpvdl$3qfkl$2@dont-email.me> |
| In reply to | #86787 |
On 10/3/2022 2:09 PM, daniel...@gmail.com wrote:
> Hello everyone,
>
> Is the C++ code below valid?
>
> #include <iostream>
> #include <string_view>
> #include <string>
>
> template <class T, class Enable = void>
> class Foo
> {};
>
> template <class T>
> class Foo<T,typename std::enable_if<std::is_same<T,std::string>::value>::type>
> {
> public:
>
> void f(std::string s)
> {
> Foo<std::string_view> foo; // (*)
> foo.f(s);
> }
> };
>
> template <class T>
> class Foo<T, typename std::enable_if<std::is_same<T, std::string_view>::value>::type>
> {
> public:
>
> void f(std::string_view s)
> {
> std::cout << s << "\n";
> }
> };
>
> int main()
> {
> Foo<std::string> foo;
> foo.f("Hello World");
> }
>
> LLVM (clang-cl) says "yes", and outputs "Hello World".
>
> Visual Studio 2022 (v143) says "no", "'f': is not a member of 'Foo<std::basic_string_view<char,std::char_traits<char>>,void>", 17
> at line (*)
>
> Both compiled with C++17.
>
Your program is invalid (ill-formed). However, no diagnostic is required.
An issue of the same general nature can be demonstrated by a more simple
example
class C;
template <typename T = int> void foo() {
C c; // Incomplete type error? Or not?
}
int main() {
foo();
}
class C {};
Note that the above code is also quietly accepted by GCC, but rejected
by MSVC and Clang.
Briefly and informally, the rule it violates says the following: if the
interpretation of your template changes depending on its point of
instantiation, the program is ill-formed. In a more focused and formal
form: if a reference to an non-dependent name from an imaginary
instantiation that immediately follows the definition is invalid, the
program is ill-formed.
A complete set of formal requirements can be found in [temp.res]:
https://timsong-cpp.github.io/cppwp/n4659/temp.res#8.3
https://timsong-cpp.github.io/cppwp/n4659/temp.res#8.4
https://timsong-cpp.github.io/cppwp/n4659/temp.res#temp.point-8
The first two links deal with non-dependent names, while the third one
applies to dependent names. But the general idea is the same: if the
meaning of a template specialization depends on its point of
instantiation, the program is ill-formed. If the meaning of a template
specialization changes as you move it up and down in the translation
unit, the program is ill-formed. Yet, no diagnostic is required.
This is basically it.
But there's another detail at play here. The freedom provided by "no
diagnostic is required" supplies the implementations with quite a bit of
leeway in choosing the point of instantiation. The obvious next logical
step is the resolution of DR#993
https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#993
It allows implementations to stop worrying about choosing the proper
point of instantiation completely. It allows them to simply push all
instantiations to the very end of the translation unit and be done with it.
This is an opportunity GCC immediately took advantage of. GCC
instantiates templates at the very end of the TU and, expectedly,
interprets their content from that vantage point. Which is why GCC
reports errors neither in your example nor in mine. Meanwhile, Clang and
MSVC still stick to the "early instantiation" approach, which allows
them to see the problems in our examples.
--
Best regards,
Andrey
[toc] | [prev] | [next] | [standalone]
| From | Andrey Tarasevich <andreytarasevich@hotmail.com> |
|---|---|
| Date | 2022-10-08 11:18 -0700 |
| Message-ID | <thseta$83se$1@dont-email.me> |
| In reply to | #86832 |
On 10/7/2022 12:41 PM, Andrey Tarasevich wrote: > > This is an opportunity GCC immediately took advantage of. GCC > instantiates templates at the very end of the TU and, expectedly, > interprets their content from that vantage point. Which is why GCC > reports errors neither in your example nor in mine. Meanwhile, Clang and > MSVC still stick to the "early instantiation" approach, which allows > them to see the problems in our examples. > Oh, I see that it was actually Clang that accepted the code... Frankly, I'm having hard time trying to find a single version of Clang that would accept it. GCC complains too, since partial specialization after instantiation is a different kind of error. And a well-diagnosable one. Which version of Clang were you using? -- Best regards, Andrey
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c++
csiph-web