Boost logo

Boost :

From: danl_miller (danl_miller_at_[hidden])
Date: 2002-02-19 20:42:54


--- In boost_at_y..., "mfdylan" <dylan_at_m...> wrote:
> --- In boost_at_y..., "danl_miller" <danl_miller_at_b...> wrote:
> > as: "The storage classes in C++ are static, auto, register, and
> > volatile except that auto is weird in that it also is combinable
> with
> > other storage classes (i.e. the true storage classes) to have
> > non-storage-class behavior."
>
> volatile is not a storage class, it's a cv-qualifier like const.
> And in fact in C you could also omit the storage class and specify
> just the cv-qualifier:
>
> main()
> {
> volatile i = 0;
> const j = 0;
> }
>
> If we allowed this for the proposed implicit typing scheme then
given:
>
> void foo(std::string s)
> {
> const t = s.c_str();
> ...
> }
>
> Would the type of t be const char* or const char* const? (I would
> have thought the latter).

  Good point. My gaff stimulated something productive. I amend my
previous attempt to redirect the auto proposal away from merely auto.
 Instead of considering the type-implied-by-initialization language
feature to be triggered by the presence of auto, let's consider the
type-implied-by-initialization language feature to be triggered by the
presence of a storage-class and/or cv-qualifier without the rest of
the type. Reworking my prior troublesome examples:

  Consider:

> void fooNonconstNonconst()
> {
> int i = 11;
> int j = 3;
> auto hmmm1 = i+j; // const? or noncost?
> ++hmmm1; // legal? or illegal?
> }

  which would become:

void fooNonconstNonconst()
{
int i = 11;
int j = 3;
const hmmm1_a = i+j; // definitely constant
auto hmmm1_b = i+j; // nonconst variable by lack of const
auto const hmmm1_c = i+j; // definitely constant
++hmmm1_b; // definitely legal
}

  Likewise consider:

> void fooConstConst()
> {
> const int x = 12;
> const int y = 4;
> auto hmmm2 = x+y; // const? or noncost?
> ++hmmm2; // legal? or illegal?
> }

  which would become:

void fooConstConst()
{
const int x = 12;
const int y = 4;
const hmmm2_a = x+y; // definitely constant
auto hmmm2_b = x+y; // nonconst variable by lack of const
auto const hmmm2_c = x+y; // definitely constant
++hmmm2_b; // definitely legal
}

  Likewise consider:

> void fooConstNonconst()
> {
> const int p = 13;
> int q = 5;
> auto hmmm3 = p+q; // const? or noncost?
> ++hmmm3; // legal? or illegal?
> }

  which would become:

void fooConstNonconst()
{
const int p = 13;
int q = 5;
const hmmm3_a = p+q; // definitely constant
auto hmmm3_b = p+q; // nonconst variable by lack of const
auto const hmmm3_c = p+q; // definitely constant
++hmmm3_b; // definitely legal
}

  As we can see, all of the troublesome cases which my prior email
mentioned are cured with the adjustment where the type-deduction does
not transfer the rvalue's storage-class to the lvalue nor transfer the
rvalue's cv-qualifier to the lvalue. The proposed
type-implied-by-initialization language feature would be limited to:

  A) transferring the simple-type-specifier from rvalue to lvalue

  B) not transferring the storage class from rvalue to lvalue:
mutable, register, auto, static, extern

  C) transferring only the cv-qualifiers of the types pointed to by
pointers or referenced by references (not transferring the
cv-qualifier present or implied by the pointer or reference address).
 For example:

     C1) transferring the const on the following because it is not the
pointer's address which is constant but rather the characters in the
array are constant

      void foo()
      {
        const char* c = "CONSTANT";
        volatile v = c; // c is type auto const char*
                        // but v is of type auto const char* volatile
                        // where the const is required, otherwise
                        // the constant string literal "CONSTANT"
                        // would be modifiable if v were to be
                        // incorrectly implied to be of type
                        // auto char* volatile
      }

     C2) not transferring the const on the following because it is the
reference's address which is constant but rather the integer's value
is permitted to change

      void bar( int parm_ )
      {
        int& r = parm_;
        auto p = &r; // &r is a constant address/pointer
                        // but p is implied to be of type int*
                        // where the constantness of the reference's
                        // address (a natural property of references)
                        // does not cause p to be constant. If one
                        // wanted p's address to be constant, then
                        // the expressivity is there as shown by pc:
        auto const pc = &r;
      }

  Enhancing content from my prior email, the concept of a declaration
becomes one of the following (in simplified colloquial grammar):

  1) storage-class type identifier and so forth
     e.g., the existing
         static int foo;
     and
         auto float bar;

  2) storage-class cv-qualifier type identifier and so forth
     e.g., the existing
         extern const float pi;
     and
         static volatile int* asicRegister;

  3) type identifier and so forth
     e.g., the existing
         int foo;
     and
         float bar;

  4) storage-class identifier and so forth
     e.g., the proposed
         auto fooNonconst = "example";
     for a nonconst pointer to constant char array but also
         static barNonconst = 3.1415F
     for a variable float

  5) storage-class cv-qualifier identifier and so forth
     e.g., the proposed
         auto volatile fooVolatile = "initial string";
     for a volatile pointer to constant char array but also
         static const barConst = 3.1415F
     for a constant float

  (BTW, my now-fortuitous gaff was that I knew there were historically
4 storage classes---oops, now 5 nowadays including mutable. In my
tight time-period that I had to get all of those thoughts out, my
brain glommed onto volatile as the 4th storage class instead of
extern.)

> Also it's not clear whether specifying the storage class after the
cv-
> qualifier is allowed (Comeau online gives a warning).
>
> extern is the other storage class, which can only be used to
> initialise a variable outside of block scope.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk