Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.std.c++ > #447

Re: Why this behaviour for literal types?

From Jason McKesson<jmckesson@gmail.com>
Newsgroups comp.std.c++
Subject Re: Why this behaviour for literal types?
Date 2012-03-17 07:50 -0700
Organization http://groups.google.com
Message-ID <19054805.1279.1331974571518.JavaMail.geo-discussion-forums@pbbpk10> (permalink)
References <1615055.1458.1331755052471.JavaMail.geo-discussion-forums@vbgx21> <jjr2a2$bdt$1@dont-email.me> <10974227.651.1331889037040.JavaMail.geo-discussion-forums@vbbed8>

Show all headers | View raw


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<mutex>
>  >
>  >  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                      ]

Back to comp.std.c++ | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

Why this behaviour for literal types? Andrzej Krzemieński<akrzemi1@gmail.com> - 2012-03-14 13:33 -0700
  Re: Why this behaviour for literal types? Daniel Krügler<daniel.kruegler@googlemail.com> - 2012-03-15 11:33 -0700
    Re: Why this behaviour for literal types? Andrzej Krzemieński <akrzemi1@gmail.com> - 2012-03-17 00:53 -0700
      Re: Why this behaviour for literal types? Jason McKesson<jmckesson@gmail.com> - 2012-03-17 07:50 -0700
      Re: Why this behaviour for literal types? Daniel Krügler<daniel.kruegler@googlemail.com> - 2012-03-18 11:31 -0700

csiph-web