Read-only data members

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • David Gausebeck

    Read-only data members

    The inability to denote data members as read-only in C++ is something
    which has annoyed me (slightly) for a while now. You can always get
    around it with accessor methods that return const references, but
    classes with huge lists of accessors often seem awkward/ugly.

    So I finally sat down and thought of a syntax I'd like to see as a
    fix. I certainly don't expect to ever see it introduced, but it's
    interesting to think about.

    The syntax is to add a new keyword, "expose", which can only be used
    in class declarations. After expose, you redeclare an existing class
    member with a greater degree of const-ness, at a different protection
    level. It might be necessary to only expose a member after that
    member's declaration, but for this example I'll assume you can use it
    before:

    class Foo {
    public:
    // public can read the string contents
    expose const char* const str;
    protected:
    // derived classes can modify the string contents
    expose char* const str;
    private:
    // only Foo can change str itself
    char* str;
    };

    My questions for the group are:
    1) Would compilers have any problem handling this syntax and its
    effects? It seems like it would be relatively easy to handle, but
    I don't know all that much about compilers.
    2) Are there any flaws with the syntax or its effects? i.e. would it
    lead to any ambiguous situations or have undesirable side effects?
    3) Do you think that, if this syntax were magically added to C++, it
    would be a good/useful thing or a bad/useless thing?

    -Dave
  • jeffc

    #2
    Re: Read-only data members


    "David Gausebeck" <gausebec@paypa l.com> wrote in message
    news:3f57a5c4.5 16215942@news.c is.dfn.de...[color=blue]
    > The inability to denote data members as read-only in C++ is something
    > which has annoyed me (slightly) for a while now.[/color]

    I couldn't understand from your post why "const" doesn't provide read-only
    access.


    Comment

    • Agent Mulder

      #3
      Re: Read-only data members

      Nice point. I hacked out the code

      <David Gausebeck>
      class Foo {
      public:
      // public can read the string contents
      expose const char* const str;
      protected:
      // derived classes can modify the string contents
      expose char* const str;
      private:
      // only Foo can change str itself
      char* str;
      };
      </David Gausebeck>

      Expose only works for protected, doesn't it?
      In the public section, data is already 'exposed'.
      In the private section, there is nothing to expose.
      So it dresses up protected. More logical to introduce
      a 4th access specifier to handle 'protected' data members.
      It must be something starting with a p (I guess). Perhaps
      priviliged?

      -X


      Comment

      • David Gausebeck

        #4
        Re: Read-only data members

        >> The inability to denote data members as read-only in C++ is something[color=blue][color=green]
        >> which has annoyed me (slightly) for a while now.[/color]
        >
        >I couldn't understand from your post why "const" doesn't provide read-only
        >access.[/color]

        It does, but not in the way I'm talking about. I realized that line
        was unclear, but I couldn't think of a better, concise way to write
        it. So I just went on and explained in more detail below. Having
        thought about it a little more now, it would be better as:

        The inability to denote data members as read-only for public or
        protected access is something which has annoyed me (slightly) for a
        while now.

        -Dave

        Comment

        • Gianni Mariani

          #5
          Re: Read-only data members

          David Gausebeck wrote:[color=blue]
          > The inability to denote data members as read-only in C++ is something
          > which has annoyed me (slightly) for a while now. You can always get
          > around it with accessor methods that return const references, but
          > classes with huge lists of accessors often seem awkward/ugly.
          >[/color]
          ....[color=blue]
          > -Dave[/color]

          I think the accessor method technique is exactly the right solution.

          The alternative is to make the members themselves "smart members".

          This is an example, I'm sure I missed a few important things, I'll let
          you fill in the blanks.


          class Foo;

          template <typename T> class ReadOnlyMember
          {
          friend class Foo;

          public:

          operator const T & () const
          {
          return value;
          }

          protected:

          template <typename T1> const T & operator = ( T1 & vin )
          {
          value = vin;
          return value;
          }

          ReadOnlyMember( const T & vin )
          : value( vin )
          {
          }

          T value;
          };


          class Foo {
          public:
          // public can read the string contents
          ReadOnlyMember< char*> str1;

          // derived classes can modify the string contents
          ReadOnlyMember< const char*> str2;

          private:
          // only Foo can change str itself
          char* str3;

          public:

          Foo()
          : str1( "str1" ), str2( "str2" )
          {
          }

          void tester()
          {
          char xxx[2];
          str1 = xxx;
          str2 = "BBB";
          }

          };


          int main()
          {

          Foo f;

          const char * xx = f.str1;

          f.str2 = "can't do this";
          }

          Comment

          • David Gausebeck

            #6
            Re: Read-only data members

            >Nice point. I hacked out the code[color=blue]
            >
            ><David Gausebeck>
            >class Foo {
            >public:
            > // public can read the string contents
            > expose const char* const str;
            >protected:
            > // derived classes can modify the string contents
            > expose char* const str;
            >private:
            > // only Foo can change str itself
            > char* str;
            >};
            ></David Gausebeck>
            >
            >Expose only works for protected, doesn't it?[/color]

            It could be used for either protected or private members.
            [color=blue]
            >In the public section, data is already 'exposed'.[/color]

            Yes, anything declared as public couldn't be exposed further.
            [color=blue]
            >In the private section, there is nothing to expose.[/color]

            What do you mean? In the example above, it's a private member that's
            being exposed.
            [color=blue]
            >So it dresses up protected. More logical to introduce
            >a 4th access specifier to handle 'protected' data members.
            >It must be something starting with a p (I guess). Perhaps
            >priviliged?[/color]

            Even if it did only apply to protected, a different specifier
            (meaning, presumably, protected but readable by public) wouldn't be
            sufficient, because it couldn't differentiate degrees of const-ness.
            Per the example above, would a 'privileged' char* be accessible to
            public as const char* const, or just as char* const?

            -Dave

            Comment

            • jeffc

              #7
              Re: Read-only data members


              "David Gausebeck" <gausebec@paypa l.com> wrote in message
              news:3f57b737.5 20683561@news.c is.dfn.de...[color=blue][color=green][color=darkred]
              > >> The inability to denote data members as read-only in C++ is something
              > >> which has annoyed me (slightly) for a while now.[/color]
              > >
              > >I couldn't understand from your post why "const" doesn't provide[/color][/color]
              read-only[color=blue][color=green]
              > >access.[/color]
              >
              > It does, but not in the way I'm talking about. I realized that line
              > was unclear, but I couldn't think of a better, concise way to write
              > it. So I just went on and explained in more detail below. Having
              > thought about it a little more now, it would be better as:
              >
              > The inability to denote data members as read-only for public or
              > protected access is something which has annoyed me (slightly) for a
              > while now.[/color]

              Yes, I see your point.


              Comment

              • jeffc

                #8
                Re: Read-only data members


                "Ioannis Vranos" <ivr@nothis.ema ils.ru> wrote in message
                news:3f57c22c$0 $234$4d4eb98e@r ead.news.gr.uu. net...[color=blue]
                >
                > I do not think such a feature is badly needed and i also believe that we
                > must not hurry add non-badly needed features into the language.[/color]

                Well don't worry - "they" won't be hurrying to add any features "we" ask for
                :-)


                Comment

                • Peter Ammon

                  #9
                  Re: Read-only data members

                  David Gausebeck wrote:[color=blue]
                  > The inability to denote data members as read-only in C++ is something
                  > which has annoyed me (slightly) for a while now.[/color]

                  [...]

                  How about (my C++ is a little rusty so bear with me)

                  class Foo {
                  int somePrivateValu e;
                  public:
                  const int & readOnlyWay;
                  Foo();
                  };

                  Foo::Foo() : readOnlyWay(som ePrivateValue) {
                  somePrivateValu e = 10;
                  }

                  This provides a public read only accessor to somePrivateValu e via the
                  instance variable readOnlyWay, but the class itself is free to modify
                  somePrivateValu e.

                  -Peter

                  Comment

                  • Ioannis Vranos

                    #10
                    Re: Read-only data members

                    "Peter Ammon" <peter_ammon@ro cketmail.com> wrote in message
                    news:bj8r1i$dc5 $1@news.apple.c om...[color=blue]
                    > David Gausebeck wrote:[color=green]
                    > > The inability to denote data members as read-only in C++ is something
                    > > which has annoyed me (slightly) for a while now.[/color]
                    >
                    > [...]
                    >
                    > How about (my C++ is a little rusty so bear with me)
                    >
                    > class Foo {
                    > int somePrivateValu e;
                    > public:
                    > const int & readOnlyWay;
                    > Foo();
                    > };
                    >
                    > Foo::Foo() : readOnlyWay(som ePrivateValue) {
                    > somePrivateValu e = 10;
                    > }
                    >
                    > This provides a public read only accessor to somePrivateValu e via the
                    > instance variable readOnlyWay, but the class itself is free to modify
                    > somePrivateValu e.[/color]


                    Yeap, that's it. You did it. :-) One could use a const * too. Personally i
                    prefer data hiding for inside class non-constants.







                    --
                    Ioannis

                    * Programming pages: http://www.noicys.freeurl.com
                    * Alternative URL 1: http://run.to/noicys
                    * Alternative URL 2: http://www.noicys.cjb.net

                    Comment

                    • David Gausebeck

                      #11
                      Re: Read-only data members

                      >David Gausebeck wrote:[color=blue][color=green]
                      >> The inability to denote data members as read-only in C++ is something
                      >> which has annoyed me (slightly) for a while now.[/color]
                      >
                      >[...]
                      >
                      >How about (my C++ is a little rusty so bear with me)
                      >
                      >class Foo {
                      > int somePrivateValu e;
                      > public:
                      > const int & readOnlyWay;
                      > Foo();
                      >};
                      >
                      >Foo::Foo() : readOnlyWay(som ePrivateValue) {
                      > somePrivateValu e = 10;
                      >}
                      >
                      >This provides a public read only accessor to somePrivateValu e via the
                      >instance variable readOnlyWay, but the class itself is free to modify
                      >somePrivateVal ue.[/color]

                      That's pretty good; I hadn't thought of that. It's still awkward
                      enough that I'd prefer to use accessor methods, though.

                      The disadvantages I see are:
                      1) the accessor reference must have a different name from the variable
                      to which it provides access.
                      2) the references will make the object larger (typically 4 bytes each)
                      3) the reference initializer list must be updated separately, so you
                      have to edit both a .h and a .cpp to grant access. Further, the
                      reference initializer list would have to be repeated for every
                      constructor.

                      I consider 1) to be the most significant problem... it's the same
                      reason I'm not entirely happy with accessor methods: they
                      unnecessarily obfuscate what's really going on. Maybe only a little
                      bit, but every little bit hurts.

                      -Dave

                      Comment

                      • Risto Lankinen

                        #12
                        Re: Read-only data members

                        Hi!

                        "David Gausebeck" <gausebec@paypa l.com> wrote in message
                        news:3f57b737.5 20683561@news.c is.dfn.de...[color=blue]
                        >
                        > The inability to denote data members as read-only for public or
                        > protected access is something which has annoyed me (slightly) for a
                        > while now.[/color]

                        Put the variables in private section, and add const references in the
                        public section for all variables that you want to expose:

                        class C
                        {
                        private:
                        int i;
                        char *p;

                        public:
                        int const &expose_i;
                        char * const &expose_p;

                        // etc...
                        };

                        BTW, this is actually an argument for making the declaration
                        level initializer legal for [at least] reference members, like it is
                        already for static members. If the initializer was allowed to be
                        present in the class declaration, as shown below...

                        public:
                        int const &expose_i = i;
                        char * const &expose_p = p;

                        .... then the compiler could optimize the references away from
                        the run-time manifestation of the object altogether, since all users
                        of the class would have to include the class declaration anyway,
                        and all translation units would therefore know at all times what
                        actual data item the reference will alias. Since this could not
                        vary, it would not need to be stored in the object itself.

                        Cheers!

                        - Risto -



                        Comment

                        • Arbesto Pelta

                          #13
                          Re: Read-only data members

                          On Thu, 04 Sep 2003 21:31:06 GMT, David Gausebeck wrote:
                          [color=blue]
                          > The inability to denote data members as read-only in C++ is something
                          > which has annoyed me (slightly) for a while now. You can always get
                          > around it with accessor methods that return const references, but
                          > classes with huge lists of accessors often seem awkward/ugly.
                          >
                          > So I finally sat down and thought of a syntax I'd like to see as a
                          > fix. I certainly don't expect to ever see it introduced, but it's
                          > interesting to think about.
                          >
                          > The syntax is to add a new keyword, "expose", which can only be used
                          > in class declarations. After expose, you redeclare an existing class
                          > member with a greater degree of const-ness, at a different protection
                          > level. It might be necessary to only expose a member after that
                          > member's declaration, but for this example I'll assume you can use it
                          > before:
                          >
                          > class Foo {
                          > public:
                          > // public can read the string contents
                          > expose const char* const str;
                          > protected:
                          > // derived classes can modify the string contents
                          > expose char* const str;
                          > private:
                          > // only Foo can change str itself
                          > char* str;
                          > };
                          >
                          > My questions for the group are:
                          > 1) Would compilers have any problem handling this syntax and its
                          > effects? It seems like it would be relatively easy to handle, but
                          > I don't know all that much about compilers.
                          > 2) Are there any flaws with the syntax or its effects? i.e. would it
                          > lead to any ambiguous situations or have undesirable side effects?
                          > 3) Do you think that, if this syntax were magically added to C++, it
                          > would be a good/useful thing or a bad/useless thing?
                          >
                          > -Dave[/color]

                          I think that the an accessor method offer an advantage: it isolate class
                          interface from attributes implementation.

                          You now use a char* to the str attribute but tomorrow maybe you want to use
                          a stl string and then you will have a problem with your str 'direct
                          exposition'.

                          Now : const char* GetStr() const { return str; }
                          Tomorrow : const char* GetStr() const { return str.c_str(); }

                          -Arbesto

                          Comment

                          • Ioannis Vranos

                            #14
                            Re: Read-only data members

                            "Risto Lankinen" <rlankine@hotma il.com> wrote in message
                            news:YhY5b.1184 5$g4.235488@new s1.nokia.com...[color=blue]
                            >
                            > Put the variables in private section, and add const references in the
                            > public section for all variables that you want to expose:
                            >
                            > class C
                            > {
                            > private:
                            > int i;
                            > char *p;
                            >
                            > public:
                            > int const &expose_i;
                            > char * const &expose_p;
                            >
                            > // etc...
                            > };
                            >
                            > BTW, this is actually an argument for making the declaration
                            > level initializer legal for [at least] reference members, like it is
                            > already for static members. If the initializer was allowed to be
                            > present in the class declaration, as shown below...
                            >
                            > public:
                            > int const &expose_i = i;
                            > char * const &expose_p = p;
                            >
                            > ... then the compiler could optimize the references away from
                            > the run-time manifestation of the object altogether, since all users
                            > of the class would have to include the class declaration anyway,
                            > and all translation units would therefore know at all times what
                            > actual data item the reference will alias. Since this could not
                            > vary, it would not need to be stored in the object itself.[/color]


                            Since there is a reference for every object you create, why it would be able
                            to optimise the references away and why it cannot do it while using a
                            constructor? Providing the above ability seems to me that two ways of object
                            construction would be provided complicating the construction/destruction
                            rules.

                            Using constructors we have simple rules and much control on the construction
                            of an object.







                            --
                            Ioannis

                            * Programming pages: http://www.noicys.freeurl.com
                            * Alternative URL 1: http://run.to/noicys
                            * Alternative URL 2: http://www.noicys.cjb.net

                            Comment

                            • Risto Lankinen

                              #15
                              Re: Read-only data members

                              Hi!

                              "Ioannis Vranos" <ivr@nothis.ema ils.ru> wrote in message
                              news:3f58abc7$0 $241$4d4eb98e@r ead.news.gr.uu. net...[color=blue]
                              > "Risto Lankinen" <rlankine@hotma il.com> wrote in message
                              > news:YhY5b.1184 5$g4.235488@new s1.nokia.com...[color=green]
                              > >
                              > > If the initializer was allowed to be
                              > > present in the class declaration, as shown below...
                              > >
                              > > public:
                              > > int const &expose_i = i;
                              > > char * const &expose_p = p;
                              > >
                              > > ... then the compiler could optimize the references away from
                              > > the run-time manifestation of the object altogether, ...[/color]
                              >
                              > Since there is a reference for every object you create, why it would be[/color]
                              able[color=blue]
                              > to optimise the references away and why it cannot do it while using a
                              > constructor?[/color]

                              The compiler could, for every dereference of 'expose_i'
                              simply compile a dereference of 'i' without having to store
                              the actual reference into the object itself. This can take
                              place in any compilation unit that includes the class header
                              containing the hypothetical initializer. This optimization
                              will be robust only if all compilation units implement it
                              identically (e.g. no other compilation parameter, such as
                              an optimization-level switch, is a factor of whether this
                              optimization were applied in a particular instance, or not).

                              The constructor-based member initialization will bury the
                              initializations to wherever the constructor is implemented,
                              which [typically] will not be visible to the compilation unit
                              that uses the class, hence the only way to communicate the
                              value of the initializer to the users of the class is to expend
                              a data item for it. Furthermore, the compiler would have
                              to scan multiple constructors to find out if the initialization
                              is indeed identical in all of them (a requirement for this
                              optimization to work).

                              In summary, allowing class-based reference initialization (as
                              opposed to the existing instance-based) would provide the
                              compiler with an opportunity to optimize away the storage
                              required by the initializer value, whenever its value can be
                              deterministical ly [re]calculated in compile-time without side
                              effects.

                              Cheers!

                              - Risto -



                              Comment

                              Working...