Path: csiph.com!usenet.pasdenom.info!news.albasani.net!.POSTED!not-for-mail From: Jason McKesson Newsgroups: comp.std.c++ Subject: Re: Why this behaviour for literal types? Date: Sat, 17 Mar 2012 07:50:15 -0700 (PDT) Organization: http://groups.google.com Lines: 112 Sender: std-cpp-request@vandevoorde.com Approved: stephen.clamage@oracle.com Message-ID: <19054805.1279.1331974571518.JavaMail.geo-discussion-forums@pbbpk10> References: <1615055.1458.1331755052471.JavaMail.geo-discussion-forums@vbgx21> <10974227.651.1331889037040.JavaMail.geo-discussion-forums@vbbed8> NNTP-Posting-Host: QhP1XiVpo0IRTVuCP6u8aa8zBuJpQh3hC1wKxwbbxeE= Content-Type: text/plain; charset=UTF-8 X-Trace: news.albasani.net oejz/rvL2POH1I5mtGF4QhTUcp+Gujq4l2Li3GIE1oeiTpYGFPc0KxSZa6axqbrckCcCUjPHW804vS4Vl7sYUA== X-Complaints-To: abuse@albasani.net NNTP-Posting-Date: Sat, 17 Mar 2012 14:50:18 +0000 (UTC) X-Mailer: Perl5 Mail::Internet v2.05 X-Submission-Address: std-cpp-submit@vandevoorde.com Cancel-Lock: sha1:ZDLBnhAzE28RwdSkd0aqiEmUQ8I= X-Original-Date: Sat, 17 Mar 2012 01:56:11 -0700 (PDT) Xref: csiph.com comp.std.c++:447 On Saturday, March 17, 2012 12:53:23 AM UTC-7, Andrzej Krzemieński wrote: > W dniu czwartek, 15 marca 2012, 19:33:34 UTC+1 użytkownik Daniel > Krügler napisał: > > Am 14.03.2012 21:33, schrieb Andrzej Krzemieński: > > > Hi, > > > This is my literal type: > > > > > > struct C > > > { > > > double m; > > > constexpr C( double m ) : m{m} {}; > > > constexpr double get() const { return m; }; > > > }; > > > > > > Therefore the following code works: > > > > > > constexpr C c = C{5.}; > > > constexpr double k = c.get(); > > > > Correct. > > > > > But the following does not: > > > > > > const C cc = C{5.}; // but not constexpr > > > constexpr double kk = cc.get(); > > > > > > Why is this so? Object cc is subject to const initialization anyway. It is possible to make it work only by a seemingly irrelevant change in declaration (add constexpr). What was the reason for disallowing this "implicit generation of compile-time constants"? > > > > This was a deliberate decision. Variables declared with const share > > different responsibilities, while constexpr is much clearer. const means > > (a) "cannot modify", it can also mean (b) constant initialization, *and* > > it can mean (c) that the variable can be used within constant expressions. > > > > const int n1 = 12; > > > > satisfies all three requirements, while > > > > int f(); > > > > const int n2 = f(); > > > > only the first. One other interesting corner case is > > > > #include > > > > std::mutex m; > > > > satisfies only the second (I'm ignoring here address-constant expression > > within this discussion, which is a very special family of constant > > expressions). > > > > C++11 kept the very restricted use-case of const variables useable in > > constant expressions which is the special bullet in 5.19 (emphasize mine): > > > > "a non-volatile glvalue of integral or enumeration type that refers to a > > non-volatile const object with a preceding initialization, **initialized > > with a constant expression**" > > > > but didn't invest the efforts to extend this for other literal types, > > because the existing rules were surprising and not easy to understand. > > The much simpler and more general bullet > > > > "a non-volatile glvalue of literal type that refers to a non-volatile > > object defined with constexpr, or that refers to a sub-object of such an > > object" > > > > rules basically all the rest. > > > > HTH& Greetings from Bremen, > > > > Daniel Krügler > > I am now trying to understand the conditions in 5.19 P 2 and it > appears to me that the following initialization should work fine: > > struct C // C is same as above > { > double m; > constexpr C( double m ) : m{m} {}; > constexpr double get() const { return m; }; > }; > > C&& rr = C{5.}; // no const! > constexpr double kk = rr.get(); > > Reference rr is not even a reference to const. In the last line the > initializing expression involves an lvalue-to-rvalue conversion (or > not?) but I am protected by the third "unless" sub-bullet because > reference rr is a glvalue of literal type that refers to a > non-volatile temporary object whose lifetime has not ended, > initialized with a constant expression. > > Am I missing something obvious here, or should the above example just > compile fine? > > Regards, > &rzej C&& rr = C{5.}; // no const! `rr` is *not* a `constexpr`. That is becuase you did not declare it as such. It doesn't matter that `C` has a `constexpr` constructor; you must actually declare the object you construct `constexpr` for it to matter. Therefore: constexpr double kk = rr.get(); You did declare `kk` as a `constexpr`. This means that it must be initialized by an expression that contains only `constexpr` values. Since `rr` is not a `constexpr` value, it cannot be used to initialize `kk`. -- [ comp.std.c++ is moderated. To submit articles, try posting with your ] [ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ] [ --- Please see the FAQ before posting. --- ] [ FAQ: http://www.comeaucomputing.com/csc/faq.html ]