public inbox for gcc-bugs@sourceware.org help / color / mirror / Atom feed
From: "f.heckenbach@fh-soft.de" <gcc-bugzilla@gcc.gnu.org> To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/104577] needs copy constructor for class non-type template parameter Date: Wed, 28 Dec 2022 01:30:00 +0000 [thread overview] Message-ID: <bug-104577-4-KKawVU4ZW1@http.gcc.gnu.org/bugzilla/> (raw) In-Reply-To: <bug-104577-4@http.gcc.gnu.org/bugzilla/> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104577 --- Comment #3 from Frank Heckenbach <f.heckenbach@fh-soft.de> --- (In reply to mail from comment #2) > I looked a bit further into this and into what the standard says. GCC does > partially the correct thing in this case, whereas several other compilers do > the wrong thing. See https://jhellings.nl/article?articleid=1 for the full > analysis. I'm not a standard expert. However, I don't think your analysis applies to quite the same situation. Your test code uses two templates with non-type parameters, test_cases and print_nttp, and I think the critical copy occurs at the point where the value is passed from one to the other. If I avoid the latter template by turning it into "void print_nttp(const copy_counter &C)" and adjusting the callers accordingly, GCC outputs "0 0 0 0 1" as I'd expect. > The short summary: > In Clause 8 of Section [temp.param], the standard defines the value of a > non-type template argument: > "An id-expression naming a non-type template-parameter of class type T > denotes a static storage duration object of type const T known as a template > parameter object, whose value is that of the corresponding template argument > after it has been converted to the type of the template-parameter. ..." > > Hence, whatever is provided as a non-type template parameter argument (of > type S in this bug report) is converted to the type S and the value > resulting from this conversion is available within the template as an lvalue > object of type const S. > > To convert an expression to type S, you either need a constexpr copy > constructor (general case) or a constexpr move constructor (in the special > case in which you provide a movable value). (which you then demonstrate using static_cast) As I said I'm not a standard expert, but if that's so, shouldn't this program also require a copy/move constructor? GCC accepts it without one. struct S { constexpr S () = default; S (S &&) = delete; }; int main () { static_cast <S> (S{}); } But let's assume it does require one. This would then indeed apply to my original example which uses "S{}" as the template argument (which then may need to be copied/moved), but it wouldn't apply if I change it to just "i <{}>", or to an int such as this: struct S { constexpr S (int) { } S (S &&) = delete; operator int () const { return 0; } }; template <S s> int i = s; int main () { return i <0>; } Now the template argument is either an empty braced-list or the integer 0 and converting it to S does not require a copy/move constructor, but rather the default constructor or the constructor taking an int, respectively. Still GCC requires a copy/move constructor. Further notes: - If converting implies copying as you say, shouldn't GCC give 2 in the last row? First you make an explicit copy (having count 1), then it's converted to the argument of print_nttp which should yield in count 2, shouldn't it? - The list of possible explanations given under "Dissecting the issue of copy_counter" is not exhaustive: * As you briefly mention in the text below, possible changes in the standard between what the given compiler versions implement could be another explanation (which may be relevant since the feature is rather new and the respective standards have not been fully implemented by some or all of the given compilers). * Also possibly relevant, there's also the possibility that the program is correct, but the standard does allow different results. I don't know and don't claim that it is the case here, but I know there are cases where a constructor must be available, but may or may not be actually called (copy elision). So testing whether it is called may not not necessarily give the same answer as finding out whether a constructor must be available.
next prev parent reply other threads:[~2022-12-28 1:30 UTC|newest] Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top 2022-02-17 3:55 [Bug c++/104577] New: needs copy constructor to call method of " f.heckenbach@fh-soft.de 2022-02-18 1:14 ` [Bug c++/104577] needs copy constructor for " pinskia at gcc dot gnu.org 2022-12-26 4:19 ` mail at jhellings dot nl 2022-12-28 1:30 ` f.heckenbach@fh-soft.de [this message] 2023-02-11 4:35 ` herring at lanl dot gov 2023-06-05 19:29 ` ppalka at gcc dot gnu.org
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=bug-104577-4-KKawVU4ZW1@http.gcc.gnu.org/bugzilla/ \ --to=gcc-bugzilla@gcc.gnu.org \ --cc=gcc-bugs@gcc.gnu.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).