non-const ref to temp object in member initialization

Discussion in 'C++' started by Jay, Jul 24, 2010.

  1. Jay

    Jay Guest

    Hi,

    I know the standard disallows the following for non-const X&
    parameters, i,e,
    void func(X&);
    ... func(X()); ...

    However, I can see a reasonable use for this pattern in constructor
    initialization lists, e.g.

    class C {
    public:
    C(const char* fSpec): abc_(InFile(fSpec)) {}

    private:
    ABC abc_;
    }

    InFile has non-const methods to read data from a file. However,
    because of the above language restriction, I have to either use
    const_cast on InFile, or go through all sorts of convolusions, making
    the code unnecessarily complicated. Would it be considered bad style
    to use const_cast on InFile in the above case, or is there a better
    workaround?

    Thanks.
    Jay, Jul 24, 2010
    #1
    1. Advertising

  2. Jay

    Öö Tiib Guest

    On 24 juuli, 09:06, Jay <> wrote:
    > I know the standard disallows the following for non-const X&
    > parameters, i,e,
    >   void func(X&);
    >   ... func(X()); ...


    C++ language lacks ways to mark that something passed in is a
    temporary and may not be stored for future usage nor used as l-value.
    The current solution that it must be "X const &" there is misleading
    as well. Even as "X const &" it is temporary and may not be stored, it
    only blocks its usage as l-value.

    > However, I can see a reasonable use for this pattern in constructor
    > initialization lists, e.g.
    >
    > class C {
    > public:
    >  C(const char* fSpec): abc_(InFile(fSpec)) {}
    >
    > private:
    >  ABC abc_;
    >
    > }
    >
    > InFile has non-const methods to read data from a file.  However,
    > because of the above language restriction, I have to either use
    > const_cast on InFile, or go through all sorts of convolusions, making
    > the code unnecessarily complicated.  Would it be considered bad style
    > to use const_cast on InFile in the above case, or is there a better
    > workaround?


    There are always more elegant workarounds than const_cast. Lets
    see ... for example some char* walking proudly around is smelly as
    well. What about getting rid of both:

    class C
    {
    public:
    C( InFile& if )
    : abc_( if )
    {}

    private:
    ABC abc_;
    }
    Öö Tiib, Jul 24, 2010
    #2
    1. Advertising

  3. Jay

    Jay Guest

    On Jul 24, 4:31 pm, Öö Tiib <> wrote:
    > There are always more elegant workarounds than const_cast. Lets
    > see ... for example some char* walking proudly around is smelly as
    > well. What about getting rid of both:
    >
    >  class C
    >  {
    >  public:
    >      C( InFile& if )
    >              : abc_( if )
    >      {}
    >
    >  private:
    >      ABC abc_;
    >  }- Hide quoted text -
    >
    > - Show quoted text -


    Perhaps I oversimplified my exmaple too much. The actual situation is
    more like

    class C
    {
    public:
    C( unsigned id )
    : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    {}

    private:
    static const char* privateMappingFromIdToFspec(unsigned);

    private:
    ABC abc_;
    }

    The only thing client code knows is the 'id'. It doesn't need to know
    that a file is even involved in initialization, let alone the file
    name. Thanks.
    Jay, Jul 24, 2010
    #3
  4. Jay

    Öö Tiib Guest

    On 24 juuli, 11:26, Jay <> wrote:
    > On Jul 24, 4:31 pm, Öö Tiib <> wrote:
    >
    >
    >
    > > There are always more elegant workarounds than const_cast. Lets
    > > see ... for example some char* walking proudly around is smelly as
    > > well. What about getting rid of both:

    >
    > >  class C
    > >  {
    > >  public:
    > >      C( InFile& if )
    > >              : abc_( if )
    > >      {}

    >
    > >  private:
    > >      ABC abc_;
    > >  }- Hide quoted text -

    >
    > > - Show quoted text -

    >
    > Perhaps I oversimplified my exmaple too much.  The actual situation is
    > more like
    >
    > class C
    > {
    > public:
    >   C( unsigned id )
    >           : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    >   {}
    >
    > private:
    >   static const char* privateMappingFromIdToFspec(unsigned);
    >
    > private:
    >   ABC abc_;
    >
    > }
    >
    > The only thing client code knows is the 'id'.  It doesn't need to know
    > that a file is even involved in initialization, let alone the file
    > name.  Thanks.


    The real problem is that no one seemingly wants to take the ownership
    and responsibility of that Infile and so it is implementation
    temporary in somewhere between. Either ABC has to be responsible that
    everything is fine with it or C has to take responsibility or someone
    passing it to C has to be responsible.
    Öö Tiib, Jul 24, 2010
    #4
  5. Jay

    Jay Guest

    On Jul 24, 6:44 pm, Öö Tiib <> wrote:
    > On 24 juuli, 11:26, Jay <> wrote:
    >
    >
    >
    >
    >
    > > On Jul 24, 4:31 pm, Öö Tiib <> wrote:

    >
    > > > There are always more elegant workarounds than const_cast. Lets
    > > > see ... for example some char* walking proudly around is smelly as
    > > > well. What about getting rid of both:

    >
    > > >  class C
    > > >  {
    > > >  public:
    > > >      C( InFile& if )
    > > >              : abc_( if )
    > > >      {}

    >
    > > >  private:
    > > >      ABC abc_;
    > > >  }- Hide quoted text -

    >
    > > > - Show quoted text -

    >
    > > Perhaps I oversimplified my exmaple too much.  The actual situation is
    > > more like

    >
    > > class C
    > > {
    > > public:
    > >   C( unsigned id )
    > >           : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    > >   {}

    >
    > > private:
    > >   static const char* privateMappingFromIdToFspec(unsigned);

    >
    > > private:
    > >   ABC abc_;

    >
    > > }

    >
    > > The only thing client code knows is the 'id'.  It doesn't need to know
    > > that a file is even involved in initialization, let alone the file
    > > name.  Thanks.

    >
    > The real problem is that no one seemingly wants to take the ownership
    > and responsibility of that Infile and so it is implementation
    > temporary in somewhere between. Either ABC has to be responsible that
    > everything is fine with it or C has to take responsibility or someone
    > passing it to C has to be responsible.- Hide quoted text -
    >
    > - Show quoted text -


    Well, from my understanding, this is the sequence of events:
    - privateMappingFromIdToFSpec gets called and returns
    - InFile constructor gets called (opens file) and returns
    - abc_ constructor gets called, uses temporary InFile object, and
    returns
    - InFile destructor gets called (closes file)

    InFile only needs to exists for the duration of the abc_ contructor.
    It is created expressly for the abc_ contructor, and cleans up right
    after it returns -- perfect example of RAII.
    Jay, Jul 24, 2010
    #5
  6. Jay

    Öö Tiib Guest

    On 24 juuli, 14:11, Jay <> wrote:
    > On Jul 24, 6:44 pm, Öö Tiib <> wrote:
    >
    >
    >
    > > On 24 juuli, 11:26, Jay <> wrote:

    >
    > > > On Jul 24, 4:31 pm, Öö Tiib <> wrote:

    >
    > > > > There are always more elegant workarounds than const_cast. Lets
    > > > > see ... for example some char* walking proudly around is smelly as
    > > > > well. What about getting rid of both:

    >
    > > > >  class C
    > > > >  {
    > > > >  public:
    > > > >      C( InFile& if )
    > > > >              : abc_( if )
    > > > >      {}

    >
    > > > >  private:
    > > > >      ABC abc_;
    > > > >  }- Hide quoted text -

    >
    > > > > - Show quoted text -

    >
    > > > Perhaps I oversimplified my exmaple too much.  The actual situation is
    > > > more like

    >
    > > > class C
    > > > {
    > > > public:
    > > >   C( unsigned id )
    > > >           : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    > > >   {}

    >
    > > > private:
    > > >   static const char* privateMappingFromIdToFspec(unsigned);

    >
    > > > private:
    > > >   ABC abc_;

    >
    > > > }

    >
    > > > The only thing client code knows is the 'id'.  It doesn't need to know
    > > > that a file is even involved in initialization, let alone the file
    > > > name.  Thanks.

    >
    > > The real problem is that no one seemingly wants to take the ownership
    > > and responsibility of that Infile and so it is implementation
    > > temporary in somewhere between. Either ABC has to be responsible that
    > > everything is fine with it or C has to take responsibility or someone
    > > passing it to C has to be responsible.- Hide quoted text -

    >
    > Well, from my understanding, this is the sequence of events:
    > - privateMappingFromIdToFSpec gets called and returns
    > - InFile constructor gets called (opens file) and returns
    > - abc_ constructor gets called, uses temporary InFile object, and
    > returns
    > - InFile destructor gets called (closes file)
    >
    > InFile only needs to exists for the duration of the abc_ contructor.
    > It is created expressly for the abc_ contructor, and cleans up right
    > after it returns -- perfect example of RAII.


    Yes. RAII works. But the InFile feels like a ... file for me. That
    means usual set of "no such file", "network drive not available", "no
    floppy in that drive", "no read acces on that device", "unexpected end
    of file" and so on ... concerns. Who reports them to whom, who is
    responsible and who takes corrective actions? It can not just crash on
    case of problems with file?

    I did not imply that it should be data member of some class, since
    file object is needed temporarily it can be local variable in a
    function that takes responsibility and trys to open it.
    Öö Tiib, Jul 24, 2010
    #6
  7. Jay

    Jay Guest

    On Jul 24, 9:29 pm, Öö Tiib <> wrote:
    > On 24 juuli, 14:11, Jay <> wrote:
    >
    >
    >
    >
    >
    > > On Jul 24, 6:44 pm, Öö Tiib <> wrote:

    >
    > > > On 24 juuli, 11:26, Jay <> wrote:

    >
    > > > > On Jul 24, 4:31 pm, Öö Tiib <> wrote:

    >
    > > > > > There are always more elegant workarounds than const_cast. Lets
    > > > > > see ... for example some char* walking proudly around is smelly as
    > > > > > well. What about getting rid of both:

    >
    > > > > >  class C
    > > > > >  {
    > > > > >  public:
    > > > > >      C( InFile& if )
    > > > > >              : abc_( if )
    > > > > >      {}

    >
    > > > > >  private:
    > > > > >      ABC abc_;
    > > > > >  }- Hide quoted text -

    >
    > > > > > - Show quoted text -

    >
    > > > > Perhaps I oversimplified my exmaple too much.  The actual situation is
    > > > > more like

    >
    > > > > class C
    > > > > {
    > > > > public:
    > > > >   C( unsigned id )
    > > > >           : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    > > > >   {}

    >
    > > > > private:
    > > > >   static const char* privateMappingFromIdToFspec(unsigned);

    >
    > > > > private:
    > > > >   ABC abc_;

    >
    > > > > }

    >
    > > > > The only thing client code knows is the 'id'.  It doesn't need to know
    > > > > that a file is even involved in initialization, let alone the file
    > > > > name.  Thanks.

    >
    > > > The real problem is that no one seemingly wants to take the ownership
    > > > and responsibility of that Infile and so it is implementation
    > > > temporary in somewhere between. Either ABC has to be responsible that
    > > > everything is fine with it or C has to take responsibility or someone
    > > > passing it to C has to be responsible.- Hide quoted text -

    >
    > > Well, from my understanding, this is the sequence of events:
    > > - privateMappingFromIdToFSpec gets called and returns
    > > - InFile constructor gets called (opens file) and returns
    > > - abc_ constructor gets called, uses temporary InFile object, and
    > > returns
    > > - InFile destructor gets called (closes file)

    >
    > > InFile only needs to exists for the duration of the abc_ contructor.
    > > It is created expressly for the abc_ contructor, and cleans up right
    > > after it returns -- perfect example of RAII.

    >
    > Yes. RAII works. But the InFile feels like a ... file for me. That
    > means usual set of "no such file", "network drive not available", "no
    > floppy in that drive", "no read acces on that device", "unexpected end
    > of file" and so on ... concerns. Who reports them to whom, who is
    > responsible and who takes corrective actions? It can not just crash on
    > case of problems with file?
    >
    > I did not imply that it should be data member of some class, since
    > file object is needed temporarily it can be local variable in a
    > function that takes responsibility and trys to open it.- Hide quoted text -
    >
    > - Show quoted text -


    Exceptions are not a problem. If InFile's constructor throws an
    exception, then InFile won't be created and C's constructor will
    unwind. If there is a read error within ABC's contructor, then it
    will throw an exception and InFile destructor will get called as C's
    constructor unwinds. In either case, C won't get created and C's
    client code can decide how to react.

    I am not quite sure how a function would fit in here. The InFile has
    to be created within C's initializer list because of the following two
    invariants:
    - C's clients don't know about files; they just pass an id and expect
    a C.
    - ABC's constructor expects an InFile given to it. It doesn't want to
    be bothered opening a file itself, since it doesn't care whether it is
    reading from a socket or a pipe or a disk file.

    That means the only place to map from an id to an InFile is in C's
    constructor. If abc_ is an embedded member of C, then I have to use
    an initializer list. The only other option is to make it a pointer
    (ABC*), and initialize it (along with InFile) in the body of C's
    constructor. I don't like that option because then I get into all the
    ugliness and overhead of memory management and also lose locality.
    Jay, Jul 24, 2010
    #7
  8. Jay

    Öö Tiib Guest

    On 24 juuli, 15:40, Jay <> wrote:
    > On Jul 24, 9:29 pm, Öö Tiib <> wrote:
    >
    >
    >
    > > On 24 juuli, 14:11, Jay <> wrote:

    >
    > > > On Jul 24, 6:44 pm, Öö Tiib <> wrote:

    >
    > > > > On 24 juuli, 11:26, Jay <> wrote:

    >
    > > > > > On Jul 24, 4:31 pm, Öö Tiib <> wrote:

    >
    > > > > > > There are always more elegant workarounds than const_cast. Lets
    > > > > > > see ... for example some char* walking proudly around is smelly as
    > > > > > > well. What about getting rid of both:

    >
    > > > > > >  class C
    > > > > > >  {
    > > > > > >  public:
    > > > > > >      C( InFile& if )
    > > > > > >              : abc_( if )
    > > > > > >      {}

    >
    > > > > > >  private:
    > > > > > >      ABC abc_;
    > > > > > >  }- Hide quoted text -

    >
    > > > > > > - Show quoted text -

    >
    > > > > > Perhaps I oversimplified my exmaple too much.  The actual situation is
    > > > > > more like

    >
    > > > > > class C
    > > > > > {
    > > > > > public:
    > > > > >   C( unsigned id )
    > > > > >           : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    > > > > >   {}

    >
    > > > > > private:
    > > > > >   static const char* privateMappingFromIdToFspec(unsigned);

    >
    > > > > > private:
    > > > > >   ABC abc_;

    >
    > > > > > }

    >
    > > > > > The only thing client code knows is the 'id'.  It doesn't need to know
    > > > > > that a file is even involved in initialization, let alone the file
    > > > > > name.  Thanks.

    >
    > > > > The real problem is that no one seemingly wants to take the ownership
    > > > > and responsibility of that Infile and so it is implementation
    > > > > temporary in somewhere between. Either ABC has to be responsible that
    > > > > everything is fine with it or C has to take responsibility or someone
    > > > > passing it to C has to be responsible.- Hide quoted text -

    >
    > > > Well, from my understanding, this is the sequence of events:
    > > > - privateMappingFromIdToFSpec gets called and returns
    > > > - InFile constructor gets called (opens file) and returns
    > > > - abc_ constructor gets called, uses temporary InFile object, and
    > > > returns
    > > > - InFile destructor gets called (closes file)

    >
    > > > InFile only needs to exists for the duration of the abc_ contructor.
    > > > It is created expressly for the abc_ contructor, and cleans up right
    > > > after it returns -- perfect example of RAII.

    >
    > > Yes. RAII works. But the InFile feels like a ... file for me. That
    > > means usual set of "no such file", "network drive not available", "no
    > > floppy in that drive", "no read acces on that device", "unexpected end
    > > of file" and so on ... concerns. Who reports them to whom, who is
    > > responsible and who takes corrective actions? It can not just crash on
    > > case of problems with file?

    >
    > > I did not imply that it should be data member of some class, since
    > > file object is needed temporarily it can be local variable in a
    > > function that takes responsibility and trys to open it.- Hide quoted text -

    >
    > Exceptions are not a problem.  If InFile's constructor throws an
    > exception, then InFile won't be created and C's constructor will
    > unwind.  If there is a read error within ABC's contructor, then it
    > will throw an exception and InFile destructor will get called as C's
    > constructor unwinds.  In either case, C won't get created and C's
    > client code can decide how to react.
    >
    > I am not quite sure how a function would fit in here.  The InFile has
    > to be created within C's initializer list because of the following two
    > invariants:
    > - C's clients don't know about files; they just pass an id and expect
    > a C.
    > - ABC's constructor expects an InFile given to it.  It doesn't want to
    > be bothered opening a file itself, since it doesn't care whether it is
    > reading from a socket or a pipe or a disk file.


    Exactly. With all such there may be various recoverable or retryable
    "connection reset by peer" trouble. The file failure exceptions seem
    to be thrown to C's client by your design but at other place you claim
    that they do not even know about usage of files there. Do not throw
    exceptions to someone about what he is not responsible. It would be
    fair feature request that if network hiccups you retry 3 times to
    produce ABC and now please display how you maintain your code to
    satisfy that request?

    > That means the only place to map from an id to an InFile is in C's
    > constructor.  If abc_ is an embedded member of C, then I have to use
    > an initializer list.  The only other option is to make it a pointer
    > (ABC*), and initialize it (along with InFile) in the body of C's
    > constructor.  I don't like that option because then I get into all the
    > ugliness and overhead of memory management and also lose locality.


    Oh no, there are lot more ways. For example a function that takes "id"
    or "fspec" and returns ABC. That function is responsible for trying to
    manage with InFile (or other sockets/pipes involved) and throws to
    client happen only on cases when it diagnoses that it does not manage.
    I am not sure if return value optimization applies here, but it
    probably does not matter since bottleneck is likely in file I/O
    anyway.
    Öö Tiib, Jul 24, 2010
    #8
  9. Jay

    Jay Guest

    On Jul 24, 11:19 pm, Öö Tiib <> wrote:
    > On 24 juuli, 15:40, Jay <> wrote:
    >
    >
    >
    >
    >
    > > On Jul 24, 9:29 pm, Öö Tiib <> wrote:

    >
    > > > On 24 juuli, 14:11, Jay <> wrote:

    >
    > > > > On Jul 24, 6:44 pm, Öö Tiib <> wrote:

    >
    > > > > > On 24 juuli, 11:26, Jay <> wrote:

    >
    > > > > > > On Jul 24, 4:31 pm, Öö Tiib <> wrote:

    >
    > > > > > > > There are always more elegant workarounds than const_cast. Lets
    > > > > > > > see ... for example some char* walking proudly around is smelly as
    > > > > > > > well. What about getting rid of both:

    >
    > > > > > > >  class C
    > > > > > > >  {
    > > > > > > >  public:
    > > > > > > >      C( InFile& if )
    > > > > > > >              : abc_( if )
    > > > > > > >      {}

    >
    > > > > > > >  private:
    > > > > > > >      ABC abc_;
    > > > > > > >  }- Hide quoted text -

    >
    > > > > > > > - Show quoted text -

    >
    > > > > > > Perhaps I oversimplified my exmaple too much.  The actual situation is
    > > > > > > more like

    >
    > > > > > > class C
    > > > > > > {
    > > > > > > public:
    > > > > > >   C( unsigned id )
    > > > > > >           : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    > > > > > >   {}

    >
    > > > > > > private:
    > > > > > >   static const char* privateMappingFromIdToFspec(unsigned);

    >
    > > > > > > private:
    > > > > > >   ABC abc_;

    >
    > > > > > > }

    >
    > > > > > > The only thing client code knows is the 'id'.  It doesn't need to know
    > > > > > > that a file is even involved in initialization, let alone the file
    > > > > > > name.  Thanks.

    >
    > > > > > The real problem is that no one seemingly wants to take the ownership
    > > > > > and responsibility of that Infile and so it is implementation
    > > > > > temporary in somewhere between. Either ABC has to be responsible that
    > > > > > everything is fine with it or C has to take responsibility or someone
    > > > > > passing it to C has to be responsible.- Hide quoted text -

    >
    > > > > Well, from my understanding, this is the sequence of events:
    > > > > - privateMappingFromIdToFSpec gets called and returns
    > > > > - InFile constructor gets called (opens file) and returns
    > > > > - abc_ constructor gets called, uses temporary InFile object, and
    > > > > returns
    > > > > - InFile destructor gets called (closes file)

    >
    > > > > InFile only needs to exists for the duration of the abc_ contructor..
    > > > > It is created expressly for the abc_ contructor, and cleans up right
    > > > > after it returns -- perfect example of RAII.

    >
    > > > Yes. RAII works. But the InFile feels like a ... file for me. That
    > > > means usual set of "no such file", "network drive not available", "no
    > > > floppy in that drive", "no read acces on that device", "unexpected end
    > > > of file" and so on ... concerns. Who reports them to whom, who is
    > > > responsible and who takes corrective actions? It can not just crash on
    > > > case of problems with file?

    >
    > > > I did not imply that it should be data member of some class, since
    > > > file object is needed temporarily it can be local variable in a
    > > > function that takes responsibility and trys to open it.- Hide quoted text -

    >
    > > Exceptions are not a problem.  If InFile's constructor throws an
    > > exception, then InFile won't be created and C's constructor will
    > > unwind.  If there is a read error within ABC's contructor, then it
    > > will throw an exception and InFile destructor will get called as C's
    > > constructor unwinds.  In either case, C won't get created and C's
    > > client code can decide how to react.

    >
    > > I am not quite sure how a function would fit in here.  The InFile has
    > > to be created within C's initializer list because of the following two
    > > invariants:
    > > - C's clients don't know about files; they just pass an id and expect
    > > a C.
    > > - ABC's constructor expects an InFile given to it.  It doesn't want to
    > > be bothered opening a file itself, since it doesn't care whether it is
    > > reading from a socket or a pipe or a disk file.

    >
    > Exactly. With all such there may be various recoverable or retryable
    > "connection reset by peer" trouble. The file failure exceptions seem
    > to be thrown to C's client by your design but at other place you claim
    > that they do not even know about usage of files there. Do not throw
    > exceptions to someone about what he is not responsible. It would be
    > fair feature request that if network hiccups you retry 3 times to
    > produce ABC and now please display how you maintain your code to
    > satisfy that request?
    >
    > > That means the only place to map from an id to an InFile is in C's
    > > constructor.  If abc_ is an embedded member of C, then I have to use
    > > an initializer list.  The only other option is to make it a pointer
    > > (ABC*), and initialize it (along with InFile) in the body of C's
    > > constructor.  I don't like that option because then I get into all the
    > > ugliness and overhead of memory management and also lose locality.

    >
    > Oh no, there are lot more ways. For example a function that takes "id"
    > or "fspec" and returns ABC. That function is responsible for trying to
    > manage with InFile (or other sockets/pipes involved) and throws to
    > client happen only on cases when it diagnoses that it does not manage.
    > I am not sure if return value optimization applies here, but it
    > probably does not matter since bottleneck is likely in file I/O
    > anyway.- Hide quoted text -
    >
    > - Show quoted text -


    Good points. My intent with the exceptions was more of a reporting
    activity. About the only thing C's clients can do is to report
    failure, giving the exception as the cause. They could try calling
    C's constructor again, but other members of C may not be amenable to
    reconstruction (e.g. if they already consumed their socket input).

    I like your idea of using a function with RVO. VC++ seems to allow
    such a function even though ABC forbids copy construction. It can be
    a static method in ABC and can also implement retries, I suppose.
    Thanks...
    Jay, Jul 24, 2010
    #9
  10. Jay

    Jay Guest

    On Jul 24, 10:21 pm, "Daniel T." <> wrote:
    > Jay <> wrote:
    > > On Jul 24, 6:44 pm, Öö Tiib <> wrote:
    > > > On 24 juuli, 11:26, Jay <> wrote:
    > > > > On Jul 24, 4:31 pm, Öö Tiib <> wrote:

    >
    > > > > > There are always more elegant workarounds than const_cast. Lets
    > > > > > see ... for example some char* walking proudly around is smelly
    > > > > > as well. What about getting rid of both:

    >
    > > > > >  class C
    > > > > >  {
    > > > > >  public:
    > > > > >      C( InFile& if )
    > > > > >              : abc_( if )
    > > > > >      {}

    >
    > > > > >  private:
    > > > > >      ABC abc_;
    > > > > >  }

    >
    > > > > Perhaps I oversimplified my exmaple too much.  The actual
    > > > > situation is more like

    >
    > > > > class C
    > > > > {
    > > > > public:
    > > > >   C( unsigned id )
    > > > >           : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    > > > >   {}

    >
    > > > > private:
    > > > >   static const char* privateMappingFromIdToFspec(unsigned);

    >
    > > > > private:
    > > > >   ABC abc_;

    >
    > > > > }

    >
    > > > > The only thing client code knows is the 'id'.  It doesn't need to
    > > > > know that a file is even involved in initialization, let alone the
    > > > > file name.  Thanks.

    >
    > > > The real problem is that no one seemingly wants to take the
    > > > ownership and responsibility of that Infile and so it is
    > > > implementation temporary in somewhere between. Either ABC has to be
    > > > responsible that everything is fine with it or C has to take
    > > > responsibility or someone passing it to C has to be responsible.

    >
    > > Well, from my understanding, this is the sequence of events:
    > > - privateMappingFromIdToFSpec gets called and returns
    > > - InFile constructor gets called (opens file) and returns
    > > - abc_ constructor gets called, uses temporary InFile object, and
    > > returns
    > > - InFile destructor gets called (closes file)

    >
    > > InFile only needs to exists for the duration of the abc_ contructor.
    > > It is created expressly for the abc_ contructor, and cleans up right
    > > after it returns -- perfect example of RAII.

    >
    > In your both of your examples, class C and class ABC both have to know
    > about the class InFile, but the only thing C does is create an InFile
    > object. I don't see why ABC needs an InFile factory in this case. Why
    > not:
    >
    > class ABC {
    > public:
    >    ABC(const char* fSpec) {
    >       InFile(fSpec);
    >       //...
    >    }
    >
    > };
    >
    > const char* privateMappingFromIdToFspec(unsigned);
    >    // the above shouldn't be a private static in class C IMHO
    >
    > class C {
    > public:
    >    C(unsigned id) : abc_(privateMappingFromIdToFSpec(id)) { }
    >
    > };
    >
    > With the above, only ABC needs to know about InFile.- Hide quoted text -
    >
    > - Show quoted text -


    Yes, your suggestion is similar to what Oo said. I can't modify ABC's
    constructor, but I can add static helper methods.

    ABC ABC::FromFSpec(const char* fSpec)
    {
    InFile file(fSpec);
    return ABC(file);
    }

    I am surprised VC++ lets me write such a method for a class which
    forbids copy construction. Hopefully it is not a VC++ quirk and is
    portable. Thanks.
    Jay, Jul 24, 2010
    #10
  11. Jay

    Jeff Flinn Guest

    See inline below:

    Jay wrote:
    > On Jul 24, 4:31 pm, Öö Tiib <> wrote:
    >> There are always more elegant workarounds than const_cast. Lets
    >> see ... for example some char* walking proudly around is smelly as
    >> well. What about getting rid of both:
    >>
    >> class C
    >> {
    >> public:
    >> C( InFile& if )
    >> : abc_( if )
    >> {}
    >>
    >> private:
    >> ABC abc_;
    >> }- Hide quoted text -

    >
    > Perhaps I oversimplified my exmaple too much. The actual situation is
    > more like
    >
    > class C
    > {
    > public:
    > C( unsigned id )

    // : abc_( InFile( privateMappingFromIdToFSpec(id) ) )

    : abc_(abcFrom(id))
    > {}
    >
    > private:
    > static const char* privateMappingFromIdToFspec(unsigned);


    static ABC abcFrom(unsigned id)
    {
    Infile inFile( privateMappingFromIdToFSpec(id) );

    return ABC(infile);
    }

    > private:
    > ABC abc_;
    > }
    >
    > The only thing client code knows is the 'id'. It doesn't need to know
    > that a file is even involved in initialization, let alone the file
    > name. Thanks.


    ABC will need a copy constructor, but will typically be elided from a
    release build.

    Jeff
    Jeff Flinn, Jul 24, 2010
    #11
  12. Jay

    Jay Guest

    On Jul 25, 12:18 am, Jeff Flinn <> wrote:
    > See inline below:
    >
    >
    >
    >
    >
    > Jay wrote:
    > > On Jul 24, 4:31 pm, Öö Tiib <> wrote:
    > >> There are always more elegant workarounds than const_cast. Lets
    > >> see ... for example some char* walking proudly around is smelly as
    > >> well. What about getting rid of both:

    >
    > >>  class C
    > >>  {
    > >>  public:
    > >>      C( InFile& if )
    > >>              : abc_( if )
    > >>      {}

    >
    > >>  private:
    > >>      ABC abc_;
    > >>  }- Hide quoted text -

    >
    > > Perhaps I oversimplified my exmaple too much.  The actual situation is
    > > more like

    >
    > > class C
    > > {
    > > public:
    > >   C( unsigned id )

    >
    > //         : abc_( InFile( privateMappingFromIdToFSpec(id) ) )
    >
    >             : abc_(abcFrom(id))
    >
    > >   {}

    >
    > > private:
    > >   static const char* privateMappingFromIdToFspec(unsigned);

    >
    >     static ABC abcFrom(unsigned id)
    >     {
    >        Infile inFile( privateMappingFromIdToFSpec(id) );
    >
    >        return ABC(infile);
    >     }
    >
    > > private:
    > >   ABC abc_;
    > > }

    >
    > > The only thing client code knows is the 'id'.  It doesn't need to know
    > > that a file is even involved in initialization, let alone the file
    > > name.  Thanks.

    >
    > ABC will need a copy constructor, but will typically be elided from a
    > release build.
    >
    > Jeff- Hide quoted text -
    >
    > - Show quoted text -


    Well, its a bit strange. VC++ rejects the static method if ABC
    forbids copy construction, but allows it if ABC's base class forbids
    copy construction. I would have thought the method would be illegal
    in both cases...
    Jay, Jul 24, 2010
    #12
  13. Jay

    James Kanze Guest

    On Jul 24, 3:14 pm, Jay <> wrote:
    > On Jul 24, 10:21 pm, "Daniel T." <> wrote:


    [...]
    > Yes, your suggestion is similar to what Oo said. I can't
    > modify ABC's constructor, but I can add static helper methods.


    > ABC ABC::FromFSpec(const char* fSpec)
    > {
    > InFile file(fSpec);
    > return ABC(file);
    > }


    > I am surprised VC++ lets me write such a method for a class which
    > forbids copy construction. Hopefully it is not a VC++ quirk and is
    > portable.


    If ABC forbids copy construction, an ABC can be neither passed
    by value nor returned from a function.

    There is on hack which can be used to avoid any const_cast:
    provide a non-const member function in InFile which returns a
    non-const reference, and use it, e.g.:

    class InFile
    {
    //...
    InFile& me();
    };

    class C
    {
    //...
    C(int id) : abc_(InFile(mapId(id)).me()) {}
    };

    While a temporary cannot bind to a non-const reference, you can
    call non-const member functions on it.

    I'm not sure if that's really cleaner than a const_cast,
    however.

    --
    James Kanze
    James Kanze, Jul 25, 2010
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. cheeser
    Replies:
    17
    Views:
    714
    cpp_weenie
    Oct 18, 2003
  2. Replies:
    2
    Views:
    556
    Mark P
    May 9, 2005
  3. David Scarlett
    Replies:
    3
    Views:
    817
    mlimber
    Feb 7, 2006
  4. Javier
    Replies:
    2
    Views:
    542
    James Kanze
    Sep 4, 2007
  5. fungus
    Replies:
    13
    Views:
    871
    fungus
    Oct 31, 2008
Loading...

Share This Page