Passing a vector to a function expecting an array

Discussion in 'C++' started by alamaison, Jan 9, 2009.

  1. alamaison

    alamaison Guest

    Hi all,

    As rarely seen but variously recommended (see C++ Coding Standards,
    Sutter and Alexandrescu for example) I'm trying to pass a vector of
    items to a function that expects an array. The tricky part is that
    the function expects the array to be passed half-open (pointer to a
    [0], pointer to one-past-end) rather that &a[0] and a size. This
    means that I'm trying to do the following:

    vector<item> files;
    ....fill vector...
    pobject->Init(&files[0], &files[0] + files.size(), ...);

    This works fine unless the vector happens to be empty which, given
    that this function initialises a type of domain-specific collection,
    is perfectly reasonable. &files[0] triggers the STL debugging with an
    out-of-bounds error. The Init function itself has no problem with the
    situation. If it receives two identical pointers it simple creates an
    empty collection.

    Now, obviously, I can hack around this problem by passing Init a
    pointer to anything twice if files.empty() but I would like to know
    the 'proper' C++ way to do this. Can it be done gracefully?

    Many thanks.

    Alex Lamaison

    -- http://swish.sourceforge.net
     
    alamaison, Jan 9, 2009
    #1
    1. Advertising

  2. alamaison

    peter koch Guest

    On 9 Jan., 20:57, alamaison <> wrote:
    > Hi all,
    >
    > As rarely seen but variously recommended (see C++ Coding Standards,
    > Sutter and Alexandrescu for example) I'm trying to pass a vector of
    > items to a function that expects an array.  The tricky part is that
    > the function expects the array to be passed half-open (pointer to a
    > [0], pointer to one-past-end) rather that &a[0] and a size.  This
    > means that I'm trying to do the following:
    >
    > vector<item> files;
    > ...fill vector...
    > pobject->Init(&files[0], &files[0] + files.size(), ...);
    >
    > This works fine unless the vector happens to be empty which, given
    > that this function initialises a type of domain-specific collection,
    > is perfectly reasonable.  &files[0] triggers the STL debugging with an
    > out-of-bounds error.  The Init function itself has no problem with the
    > situation.  If it receives two identical pointers it simple creates an
    > empty collection.
    >
    > Now, obviously, I can hack around this problem by passing Init a
    > pointer to anything twice if files.empty() but I would like to know
    > the 'proper' C++ way to do this.  Can it be done gracefully?


    Use a function that returns a pointer to the first element of a vector
    or 0 if the vector is empty.
    This makes your function look like
    pobject->Init(dataof(files), dataof(files) + files.size(), ...);

    Which is not to bad (and not to far away from the C++0x solution
    pobject->Init(files.data(), files.data() + files.size(), ...) if my
    memory serves me)

    /Peter
     
    peter koch, Jan 9, 2009
    #2
    1. Advertising

  3. On 2009-01-09 18:42:30, peter koch wrote:

    > On 9 Jan., 20:57, alamaison <> wrote:
    >> Hi all,
    >>
    >> As rarely seen but variously recommended (see C++ Coding Standards,
    >> Sutter and Alexandrescu for example) I'm trying to pass a vector of
    >> items to a function that expects an array.  The tricky part is that
    >> the function expects the array to be passed half-open (pointer to a
    >> [0], pointer to one-past-end) rather that &a[0] and a size.  This
    >> means that I'm trying to do the following:
    >>
    >> vector<item> files;
    >> ...fill vector...
    >> pobject->Init(&files[0], &files[0] + files.size(), ...);
    >>
    >> This works fine unless the vector happens to be empty which, given
    >> that this function initialises a type of domain-specific collection,
    >> is perfectly reasonable.  &files[0] triggers the STL debugging with an
    >> out-of-bounds error.  The Init function itself has no problem with the
    >> situation.  If it receives two identical pointers it simple creates an
    >> empty collection.
    >>
    >> Now, obviously, I can hack around this problem by passing Init a
    >> pointer to anything twice if files.empty() but I would like to know
    >> the 'proper' C++ way to do this.  Can it be done gracefully?

    >
    > Use a function that returns a pointer to the first element of a vector
    > or 0 if the vector is empty.
    > This makes your function look like
    > pobject->Init(dataof(files), dataof(files) + files.size(), ...);
    >
    > Which is not to bad (and not to far away from the C++0x solution
    > pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > memory serves me)


    Or subclass the vector and add a data() function (that does the same
    thing)?

    Gerhard
     
    Gerhard Fiedler, Jan 9, 2009
    #3
  4. alamaison

    alamaison Guest

    On Jan 9, 8:42 pm, peter koch <> wrote:

    > > The tricky part is that
    > > the function expects the array to be passed half-open (pointer to a
    > > [0], pointer to one-past-end) rather that &a[0] and a size.  This
    > > means that I'm trying to do the following:

    >
    > > vector<item> files;
    > > ...fill vector...
    > > pobject->Init(&files[0], &files[0] + files.size(), ...);

    ....
    > > The Init function itself has no problem with the
    > > situation.  If it receives two identical pointers it simple creates an
    > > empty collection.

    >
    > Use a function that returns a pointer to the first element of a vector
    > or 0 if the vector is empty.
    > This makes your function look like
    > pobject->Init(dataof(files), dataof(files) + files.size(), ...);
    >
    > Which is not to bad (and not to far away from the C++0x solution
    > pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > memory serves me)


    Thanks for the answers, guys.

    Interesting. So was data() introduced to address exactly this
    concern? Unfortunately this still won't work for me as the collection
    thinks it hasn't been initialised if either of its members, which are
    set to the value of these two pointers, is NULL. I suppose the 'array
    way' of looking at it is that one-past-the-end is always a valid
    address to reference (at least according to the _C_ standard) and so
    &files[0] should be ok even for an empty array. What I need is a way
    to get this value without the debugger catching it as an error.
     
    alamaison, Jan 9, 2009
    #4
  5. alamaison

    Noah Roberts Guest

    alamaison wrote:
    > I suppose the 'array
    > way' of looking at it is that one-past-the-end is always a valid
    > address to reference (at least according to the _C_ standard) and so
    > &files[0] should be ok even for an empty array.


    No, no.

    It is always valid to look at the address of the area one past the end
    of an array. You can compare the value of this *address* to other
    values and this behavior is defined. It is NEVER valid to dereference
    that address, which is what array notation does.

    files[0] == *(files + 0)

    Thus you've caused undefined behavior before taking the address.
     
    Noah Roberts, Jan 9, 2009
    #5
  6. alamaison

    alamaison Guest

    > > > > vector<item> files;
    > > > > ...fill vector...
    > > > > pobject->Init(&files[0], &files[0] + files.size(), ...);


    > > > Use a function that returns a pointer to the first element of a vector
    > > > or 0 if the vector is empty.
    > > > This makes your function look like
    > > > pobject->Init(dataof(files), dataof(files) + files.size(), ...);


    > > Unfortunately this still won't work for me as the collection
    > > thinks it hasn't been initialised if either of its members, which are
    > > set to the value of these two pointers, is NULL.  I suppose the 'array
    > > way' of looking at it is that one-past-the-end is always a valid
    > > address to reference (at least according to the _C_ standard) and so
    > > &files[0] should be OK even for an empty array.  What I need is a way
    > > to get this value without the debugger catching it as an error.


    On Jan 9, 11:38 pm, Paavo Helde <> wrote:
    > You can't. There might be no array allocated at all for zero element
    > case, thus you cannot form a pointer past the end of it. The best you can
    > do is to check for zero size and substitute some valid pointer, like
    > NULL.
    >
    > So, &files[0] is UB even if the result is not used. MS has decided to
    > define this UB as runtime crash if checked iterators are used.
    > Ironically, without this check the code would most likely not crash
    > because in Win32 flat memory model all bit patterns constitute valid
    > pointers unless dereferenced. So it appears MS is now helping here to
    > keep the code more portable, a rare occasion ;-) You should take the
    > advice and fix the code.


    On Jan 9, 11:31 pm, Noah Roberts <> wrote:
    > It is always valid to look at the address of the area one past the end
    > of an array. You can compare the value of this *address* to other
    > values and this behavior is defined. It is NEVER valid to dereference
    > that address, which is what array notation does.
    >
    > files[0] == *(files + 0)
    >
    > Thus you've caused undefined behavior before taking the address.


    Thanks to both of you for pitching in.

    I think I may have been unclear in what I was trying to say. I
    understand _why_ the checked STL catches &files[0]. All I'm trying to
    say is that it doesn't match with how plain-old C arrays work. Just
    as Noah says, with arrays you can use the _address_ of one-past-the-
    end as a marker (that's what I meant by reference - not a good choice
    of term). This is the one and only out-of-bounds address that is
    legal to use according to the C standard; possibly this is different
    for C++. Of course, you can't dereference this address, neither do I
    want to.

    Vector is touted as a complete replacement for arrays when passing
    arguments to legacy code but I'm not sure it quite measures up if it
    can't be used in this way.

    Comments most welcome.

    Alex
     
    alamaison, Jan 10, 2009
    #6
  7. alamaison

    peter koch Guest

    [snip]
    > > It is always valid to look at the address of the area one past the end
    > > of an array.  You can compare the value of this *address* to other
    > > values and this behavior is defined.  It is NEVER valid to dereference
    > > that address, which is what array notation does.

    >
    > > files[0] == *(files + 0)

    >
    > > Thus you've caused undefined behavior before taking the address.

    >
    > Thanks to both of you for pitching in.
    >
    > I think I may have been unclear in what I was trying to say.  I
    > understand _why_ the checked STL catches &files[0].  All I'm trying to
    > say is that it doesn't match with how plain-old C arrays work.  


    Well... C-arrays can't be empty, so the analogy breaks down a bit.

    > Just
    > as Noah says, with arrays you can use the _address_ of one-past-the-
    > end as a marker (that's what I meant by reference - not a good choice
    > of term).  This is the one and only out-of-bounds address that is
    > legal to use according to the C standard; possibly this is different
    > for C++.  Of course, you can't dereference this address, neither do I
    > want to.
    >
    > Vector is touted as a complete replacement for arrays when passing
    > arguments to legacy code but I'm not sure it quite measures up if it
    > can't be used in this way.


    It can. As advised in another post, you can pass e.g. 0 if there are
    no elements in the vector. So you write e.g. x.empty? 0: &x[0] instead
    of &x[0], or you write a function if you find that to be more
    readable. It is only four lines fully templated, so it really is no
    big deal.
    C++0x has these four lines ready for you, but they are not part of C+
    +98 as originally there was no requirement that std::vector should be
    able to replace built-in arrays.

    /Peter
     
    peter koch, Jan 10, 2009
    #7
  8. alamaison

    peter koch Guest

    On 9 Jan., 22:13, Gerhard Fiedler <> wrote:
    > On 2009-01-09 18:42:30, peter koch wrote:
    >
    >
    >
    >
    >
    > > On 9 Jan., 20:57, alamaison <> wrote:
    > >> Hi all,

    >
    > >> As rarely seen but variously recommended (see C++ Coding Standards,
    > >> Sutter and Alexandrescu for example) I'm trying to pass a vector of
    > >> items to a function that expects an array.  The tricky part is that
    > >> the function expects the array to be passed half-open (pointer to a
    > >> [0], pointer to one-past-end) rather that &a[0] and a size.  This
    > >> means that I'm trying to do the following:

    >
    > >> vector<item> files;
    > >> ...fill vector...
    > >> pobject->Init(&files[0], &files[0] + files.size(), ...);

    >
    > >> This works fine unless the vector happens to be empty which, given
    > >> that this function initialises a type of domain-specific collection,
    > >> is perfectly reasonable.  &files[0] triggers the STL debugging with an
    > >> out-of-bounds error.  The Init function itself has no problem with the
    > >> situation.  If it receives two identical pointers it simple creates an
    > >> empty collection.

    >
    > >> Now, obviously, I can hack around this problem by passing Init a
    > >> pointer to anything twice if files.empty() but I would like to know
    > >> the 'proper' C++ way to do this.  Can it be done gracefully?

    >
    > > Use a function that returns a pointer to the first element of a vector
    > > or 0 if the vector is empty.
    > > This makes your function look like
    > > pobject->Init(dataof(files), dataof(files) + files.size(), ...);

    >
    > > Which is not to bad (and not to far away from the C++0x solution
    > > pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > > memory serves me)

    >
    > Or subclass the vector and add a data() function (that does the same
    > thing)?
    >


    This is a very bad idea: for one thing, you will not be able to
    support code that has already been written, and even if you rewrote
    that code, there would still be the problem with third-party
    libraries.

    /Peter
     
    peter koch, Jan 10, 2009
    #8
  9. alamaison

    alamaison Guest

    On Jan 10, 1:56 am, peter koch <> wrote:
    >
    > Well... C-arrays can't be empty, so the analogy breaks down a bit.


    True. I may be stretching the analogy too far.

    > > Vector is touted as a complete replacement for arrays when passing
    > > arguments to legacy code but I'm not sure it quite measures up if it
    > > can't be used in this way.

    >
    > It can. As advised in another post, you can pass e.g. 0 if there are
    > no elements in the vector. So you write e.g. x.empty? 0: &x[0] instead
    > of &x[0], or you write a function if you find that to be more
    > readable. It is only four lines fully templated, so it really is no
    > big deal.
    > C++0x has these four lines ready for you, but they are not part of C+
    > +98 as originally there was no requirement that std::vector should be
    > able to replace built-in arrays.


    This does seem like a pretty good solution for the general case and I
    will use it from now on. Unfortunately it doesn't work in this
    specific instance but I never really cared about that anyway. More
    interested in the principle of it.
     
    alamaison, Jan 10, 2009
    #9
  10. On 2009-01-09 23:58:47, peter koch wrote:

    >>>> As rarely seen but variously recommended (see C++ Coding Standards,
    >>>> Sutter and Alexandrescu for example) I'm trying to pass a vector
    >>>> of items to a function that expects an array.  The tricky part is
    >>>> that the function expects the array to be passed half-open
    >>>> (pointer to a [0], pointer to one-past-end) rather that &a[0] and
    >>>> a size.  This means that I'm trying to do the following:

    >>
    >>>> vector<item> files;
    >>>> ...fill vector...
    >>>> pobject->Init(&files[0], &files[0] + files.size(), ...);

    >>
    >>>> This works fine unless the vector happens to be empty which, given
    >>>> that this function initialises a type of domain-specific
    >>>> collection, is perfectly reasonable.  &files[0] triggers the STL
    >>>> debugging with an out-of-bounds error.  The Init function itself
    >>>> has no problem with the situation.  If it receives two identical
    >>>> pointers it simple creates an empty collection.

    >>
    >>>> Now, obviously, I can hack around this problem by passing Init a
    >>>> pointer to anything twice if files.empty() but I would like to
    >>>> know the 'proper' C++ way to do this.  Can it be done gracefully?

    >>
    >>> Use a function that returns a pointer to the first element of a vector
    >>> or 0 if the vector is empty.
    >>> This makes your function look like
    >>> pobject->Init(dataof(files), dataof(files) + files.size(), ...);

    >>
    >>> Which is not to bad (and not to far away from the C++0x solution
    >>> pobject->Init(files.data(), files.data() + files.size(), ...) if my
    >>> memory serves me)

    >>
    >> Or subclass the vector and add a data() function (that does the same
    >> thing)?

    >
    > This is a very bad idea: for one thing, you will not be able to
    > support code that has already been written, and even if you rewrote
    > that code, there would still be the problem with third-party
    > libraries.


    ??

    The existing code expects a pointer to the first and a pointer past the
    last element. The code that has to interface to this code is being
    written. This subclass is for code that is currently being written. If
    you receive from some other code a vector that is to be passed to that
    function, you can always cast it to the subclass.

    Can you please construct a not too constructed situation that is
    compatible with the situation as outlined above where subclassing would
    be a problem?

    Gerhard
     
    Gerhard Fiedler, Jan 10, 2009
    #10
  11. On 2009-01-09 20:51:35, alamaison wrote:

    > Unfortunately this still won't work for me as the collection thinks it
    > hasn't been initialised if either of its members, which are set to
    > the value of these two pointers, is NULL.


    You don't have to use NULL as address if the size of the array is 0. You
    should be able to use any address -- supposedly that function doesn't do
    any dereferencing in this case, just comparing with NULL and some
    pointer arithmetic. Instead of (x.empty()? 0: &x[0]) you can use
    (x.empty()? &x: &x[0]), for example.

    Gerhard
     
    Gerhard Fiedler, Jan 10, 2009
    #11
  12. alamaison

    peter koch Guest

    On 10 Jan., 12:25, Gerhard Fiedler <> wrote:
    > On 2009-01-09 23:58:47, peter koch wrote:
    >
    >
    >
    >
    >
    > >>>> As rarely seen but variously recommended (see C++ Coding Standards,
    > >>>> Sutter and Alexandrescu for example) I'm trying to pass a vector
    > >>>> of items to a function that expects an array.  The tricky part is
    > >>>> that the function expects the array to be passed half-open
    > >>>> (pointer to a [0], pointer to one-past-end) rather that &a[0] and
    > >>>> a size.  This means that I'm trying to do the following:

    >
    > >>>> vector<item> files;
    > >>>> ...fill vector...
    > >>>> pobject->Init(&files[0], &files[0] + files.size(), ...);

    >
    > >>>> This works fine unless the vector happens to be empty which, given
    > >>>> that this function initialises a type of domain-specific
    > >>>> collection, is perfectly reasonable.  &files[0] triggers the STL
    > >>>> debugging with an out-of-bounds error.  The Init function itself
    > >>>> has no problem with the situation.  If it receives two identical
    > >>>> pointers it simple creates an empty collection.

    >
    > >>>> Now, obviously, I can hack around this problem by passing Init a
    > >>>> pointer to anything twice if files.empty() but I would like to
    > >>>> know the 'proper' C++ way to do this.  Can it be done gracefully?

    >
    > >>> Use a function that returns a pointer to the first element of a vector
    > >>> or 0 if the vector is empty.
    > >>> This makes your function look like
    > >>> pobject->Init(dataof(files), dataof(files) + files.size(), ...);

    >
    > >>> Which is not to bad (and not to far away from the C++0x solution
    > >>> pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > >>> memory serves me)

    >
    > >> Or subclass the vector and add a data() function (that does the same
    > >> thing)?

    >
    > > This is a very bad idea: for one thing, you will not be able to
    > > support code that has already been written, and even if you rewrote
    > > that code, there would still be the problem with third-party
    > > libraries.

    >
    > ??
    >
    > The existing code expects a pointer to the first and a pointer past the
    > last element. The code that has to interface to this code is being
    > written. This subclass is for code that is currently being written.


    I don't know what makes you believe that. If there is no existing code-
    base, the situation is a little different, but not much.

    > If
    > you receive from some other code a vector that is to be passed to that
    > function, you can always cast it to the subclass.


    No, you can not.

    /Peter
    >
    > Can you please construct a not too constructed situation that is
    > compatible with the situation as outlined above where subclassing would
    > be a problem?
    >
    > Gerhard
     
    peter koch, Jan 10, 2009
    #12
  13. On Jan 10, 2:07 am, alamaison <> wrote:
    > On Jan 10, 1:56 am, peter koch <> wrote:
    >
    >
    >
    > > Well... C-arrays can't be empty, so the analogy breaks down a bit.

    >
    > True.  I may be stretching the analogy too far.
    >
    > > > Vector is touted as a complete replacement for arrays when passing
    > > > arguments to legacy code but I'm not sure it quite measures up if it
    > > > can't be used in this way.

    >
    > > It can. As advised in another post, you can pass e.g. 0 if there are
    > > no elements in the vector. So you write e.g. x.empty? 0: &x[0] instead
    > > of &x[0], or you write a function if you find that to be more
    > > readable. It is only four lines fully templated, so it really is no
    > > big deal.
    > > C++0x has these four lines ready for you, but they are not part of C+
    > > +98 as originally there was no requirement that std::vector should be
    > > able to replace built-in arrays.

    >
    > This does seem like a pretty good solution for the general case and I
    > will use it from now on.  Unfortunately it doesn't work in this
    > specific instance but I never really cared about that anyway.  More
    > interested in the principle of it.


    #include <vector>
    using namespace std;

    template <class T>
    const T* first (const vector <T>& v, const T* null = 0) {
    return v.empty () ? null : &v [0];
    }

    template <class T>
    const T* last (const vector <T>& v, const T* null = 0) {
    return first (v, null) + v.size ();
    }

    void test_vector_pass ()
    {
    void foo (const int* b, const int* e);

    vector <int> v;
    foo (first (v), last (v));

    int empty;
    foo (first (v, &empty), last (v, &empty));
    }

    Regards,
    Vidar Hasfjord
     
    Vidar Hasfjord, Jan 12, 2009
    #13
  14. alamaison

    alamaison Guest

    On Jan 12, 1:36 pm, Vidar Hasfjord <>
    wrote:

    > #include <vector>
    > using namespace std;
    >
    > template <class T>
    > const T* first (const vector <T>& v, const T* null = 0) {
    >   return v.empty () ? null : &v [0];
    >
    > }
    >
    > template <class T>
    > const T* last (const vector <T>& v, const T* null = 0) {
    >   return first (v, null) + v.size ();
    >
    > }
    >
    > void test_vector_pass ()
    > {
    >   void foo (const int* b, const int* e);
    >
    >   vector <int> v;
    >   foo (first (v), last (v));
    >
    >   int empty;
    >   foo (first (v, &empty), last (v, &empty));
    >
    > }


    Thanks Vidar :) Very nice!
     
    alamaison, Jan 13, 2009
    #14
  15. On Jan 10, 5:25 am, Gerhard Fiedler <> wrote:
    > On 2009-01-09 23:58:47, peter koch wrote:
    >
    >
    >
    > >>>> As rarely seen but variously recommended (see C++ Coding Standards,
    > >>>> Sutter and Alexandrescu for example) I'm trying to pass a vector
    > >>>> of items to a function that expects an array.  The tricky part is
    > >>>> that the function expects the array to be passed half-open
    > >>>> (pointer to a [0], pointer to one-past-end) rather that &a[0] and
    > >>>> a size.  This means that I'm trying to do the following:

    >
    > >>>> vector<item> files;
    > >>>> ...fill vector...
    > >>>> pobject->Init(&files[0], &files[0] + files.size(), ...);

    >
    > >>>> This works fine unless the vector happens to be empty which, given
    > >>>> that this function initialises a type of domain-specific
    > >>>> collection, is perfectly reasonable.  &files[0] triggers the STL
    > >>>> debugging with an out-of-bounds error.  The Init function itself
    > >>>> has no problem with the situation.  If it receives two identical
    > >>>> pointers it simple creates an empty collection.

    >
    > >>>> Now, obviously, I can hack around this problem by passing Init a
    > >>>> pointer to anything twice if files.empty() but I would like to
    > >>>> know the 'proper' C++ way to do this.  Can it be done gracefully?

    >
    > >>> Use a function that returns a pointer to the first element of a vector
    > >>> or 0 if the vector is empty.
    > >>> This makes your function look like
    > >>> pobject->Init(dataof(files), dataof(files) + files.size(), ...);

    >
    > >>> Which is not to bad (and not to far away from the C++0x solution
    > >>> pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > >>> memory serves me)

    >
    > >> Or subclass the vector and add a data() function (that does the same
    > >> thing)?

    >
    > > This is a very bad idea: for one thing, you will not be able to
    > > support code that has already been written, and even if you rewrote
    > > that code, there would still be the problem with third-party
    > > libraries.

    >
    > ??
    >
    > The existing code expects a pointer to the first and a pointer past the
    > last element. The code that has to interface to this code is being
    > written. This subclass is for code that is currently being written. If
    > you receive from some other code a vector that is to be passed to that
    > function, you can always cast it to the subclass.
    >
    > Can you please construct a not too constructed situation that is
    > compatible with the situation as outlined above where subclassing would
    > be a problem?
    >
    > Gerhard


    It's still a bad idea. Subclassing a class that a) you cannot modify,
    and b) does not have a virtual destructor is a recipe for disaster.
    Just don't do it.
     
    Zachary Turner, Jan 13, 2009
    #15
  16. alamaison

    James Kanze Guest

    On Jan 13, 6:21 pm, Zachary Turner <> wrote:
    > On Jan 10, 5:25 am, Gerhard Fiedler <> wrote:


    [...]
    > > >> Or subclass the vector and add a data() function (that
    > > >> does the same thing)?


    > > > This is a very bad idea: for one thing, you will not be
    > > > able to support code that has already been written, and
    > > > even if you rewrote that code, there would still be the
    > > > problem with third-party libraries.


    > > ??


    > > The existing code expects a pointer to the first and a
    > > pointer past the last element. The code that has to
    > > interface to this code is being written. This subclass is
    > > for code that is currently being written. If you receive
    > > from some other code a vector that is to be passed to that
    > > function, you can always cast it to the subclass.


    > > Can you please construct a not too constructed situation
    > > that is compatible with the situation as outlined above
    > > where subclassing would be a problem?


    > It's still a bad idea. Subclassing a class that a) you cannot
    > modify, and b) does not have a virtual destructor is a recipe
    > for disaster. Just don't do it.


    It's such a bad idea that the standard more or less requires it
    in some cases. I regularly derive from std::iterator<>,
    std::unary_function<> and std::binary_function<>, for example.
    I also have some classes of my own that are designed to be used
    in a similar manner.

    Generally speaking, std::vector wasn't designed to be used as a
    base class, so derivation from it should be very much an
    exception. But in this particular case, the exception seems
    justified, and I don't see any problem with it.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Jan 14, 2009
    #16
  17. alamaison

    peter koch Guest

    On 14 Jan., 10:04, James Kanze <> wrote:
    > On Jan 13, 6:21 pm, Zachary  Turner <> wrote:
    >
    > > On Jan 10, 5:25 am, Gerhard Fiedler <> wrote:

    >
    >     [...]
    >
    >
    >
    >
    >
    > > > >> Or subclass the vector and add a data() function (that
    > > > >> does the same thing)?
    > > > > This is a very bad idea: for one thing, you will not be
    > > > > able to support code that has already been written, and
    > > > > even if you rewrote that code, there would still be the
    > > > > problem with third-party libraries.
    > > > ??
    > > > The existing code expects a pointer to the first and a
    > > > pointer past the last element. The code that has to
    > > > interface to this code is being written. This subclass is
    > > > for code that is currently being written. If you receive
    > > > from some other code a vector that is to be passed to that
    > > > function, you can always cast it to the subclass.
    > > > Can you please construct a not too constructed situation
    > > > that is compatible with the situation as outlined above
    > > > where subclassing would be a problem?

    > > It's still a bad idea.  Subclassing a class that a) you cannot
    > > modify, and b) does not have a virtual destructor is a recipe
    > > for disaster.  Just don't do it.

    >
    > It's such a bad idea that the standard more or less requires it
    > in some cases.  I regularly derive from std::iterator<>,
    > std::unary_function<> and std::binary_function<>, for example.
    > I also have some classes of my own that are designed to be used
    > in a similar manner.
    >
    > Generally speaking, std::vector wasn't designed to be used as a
    > base class, so derivation from it should be very much an
    > exception.  But in this particular case, the exception seems
    > justified, and I don't see any problem with it.


    While I have no problems deriving from classes that are not designed
    with derivation in mind, I believe there should be some kind of
    justification for doing so. In this case, there is no justification
    whatsoever.

    /Peter
     
    peter koch, Jan 14, 2009
    #17
  18. On 2009-01-14 08:12:36, peter koch wrote:

    >>>>>> Or subclass the vector and add a data() function (that does the
    >>>>>> same thing)?
    >>>>> This is a very bad idea: for one thing, you will not be able to
    >>>>> support code that has already been written, and even if you
    >>>>> rewrote that code, there would still be the problem with
    >>>>> third-party libraries.
    >>>> ?? The existing code expects a pointer to the first and a pointer
    >>>> past the last element. The code that has to interface to this code
    >>>> is being written. This subclass is for code that is currently
    >>>> being written. If you receive from some other code a vector that
    >>>> is to be passed to that function, you can always cast it to the
    >>>> subclass. Can you please construct a not too constructed situation
    >>>> that is compatible with the situation as outlined above where
    >>>> subclassing would be a problem?
    >>> It's still a bad idea.  Subclassing a class that a) you cannot
    >>> modify, and b) does not have a virtual destructor is a recipe for
    >>> disaster.  Just don't do it.

    >>
    >> It's such a bad idea that the standard more or less requires it in
    >> some cases.  I regularly derive from std::iterator<>,
    >> std::unary_function<> and std::binary_function<>, for example. I
    >> also have some classes of my own that are designed to be used in a
    >> similar manner.
    >>
    >> Generally speaking, std::vector wasn't designed to be used as a base
    >> class, so derivation from it should be very much an exception.  But
    >> in this particular case, the exception seems justified, and I don't
    >> see any problem with it.

    >
    > While I have no problems deriving from classes that are not designed
    > with derivation in mind, I believe there should be some kind of
    > justification for doing so. In this case, there is no justification
    > whatsoever.


    The justification (and "father" of the idea) would be this (on this
    thread, by you, a while ago):

    > Which is not to bad (and not to far away from the C++0x solution
    > pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > memory serves me)


    Gerhard
     
    Gerhard Fiedler, Jan 14, 2009
    #18
  19. alamaison

    peter koch Guest

    On 14 Jan., 12:22, Gerhard Fiedler <> wrote:
    > On 2009-01-14 08:12:36, peter koch wrote:
    >
    >
    >
    >
    >
    > >>>>>> Or subclass the vector and add a data() function (that does the
    > >>>>>> same thing)?
    > >>>>> This is a very bad idea: for one thing, you will not be able to
    > >>>>> support code that has already been written, and even if you
    > >>>>> rewrote that code, there would still be the problem with
    > >>>>> third-party libraries.
    > >>>> ?? The existing code expects a pointer to the first and a pointer
    > >>>> past the last element. The code that has to interface to this code
    > >>>> is being written. This subclass is for code that is currently
    > >>>> being written. If you receive from some other code a vector that
    > >>>> is to be passed to that function, you can always cast it to the
    > >>>> subclass. Can you please construct a not too constructed situation
    > >>>> that is compatible with the situation as outlined above where
    > >>>> subclassing would be a problem?
    > >>> It's still a bad idea.  Subclassing a class that a) you cannot
    > >>> modify, and b) does not have a virtual destructor is a recipe for
    > >>> disaster.  Just don't do it.

    >
    > >> It's such a bad idea that the standard more or less requires it in
    > >> some cases.  I regularly derive from std::iterator<>,
    > >> std::unary_function<> and std::binary_function<>, for example. I
    > >> also have some classes of my own that are designed to be used in a
    > >> similar manner.

    >
    > >> Generally speaking, std::vector wasn't designed to be used as a base
    > >> class, so derivation from it should be very much an exception.  But
    > >> in this particular case, the exception seems justified, and I don't
    > >> see any problem with it.

    >
    > > While I have no problems deriving from classes that are not designed
    > > with derivation in mind, I believe there should be some kind of
    > > justification for doing so. In this case, there is no justification
    > > whatsoever.

    >
    > The justification (and "father" of the idea) would be this (on this
    > thread, by you, a while ago):
    >
    > > Which is not to bad (and not to far away from the C++0x solution
    > > pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > > memory serves me)


    Im sorry if that remark caused anyone to believe that inheritance
    would be the way to go.
    In the current situation, inheritance has no advantage from a free
    function - e.g. the one suggested by Vidar Hasfjord elsethread. (I
    would only have one function - and not two as given by Vidar, but that
    is a minor issue).

    /Peter
     
    peter koch, Jan 15, 2009
    #19
  20. On Jan 15, 6:21 pm, peter koch <> wrote:
    > On 14 Jan., 12:22, Gerhard Fiedler <> wrote:
    > [...]
    > > > While I have no problems deriving from classes that are not designed
    > > > with derivation in mind, I believe there should be some kind of
    > > > justification for doing so. In this case, there is no justification
    > > > whatsoever.

    >
    > > The justification (and "father" of the idea) would be this (on this
    > > thread, by you, a while ago):

    >
    > > > Which is not to bad (and not to far away from the C++0x solution
    > > > pobject->Init(files.data(), files.data() + files.size(), ...) if my
    > > > memory serves me)

    >
    > Im sorry if that remark caused anyone to believe that inheritance
    > would be the way to go.
    > In the current situation, inheritance has no advantage from a free
    > function - e.g. the one suggested by Vidar Hasfjord elsethread. (I
    > would only have one function - and not two as given by Vidar, but that
    > is a minor issue).


    The two-function solution is similar to Boost.Range. Taking it a step
    further:

    pointer_range <int> r (v);
    foo (r.begin (), r.end ());

    This fully encapsulates the empty case.

    Regards,
    Vidar Hasfjord
     
    Vidar Hasfjord, Jan 15, 2009
    #20
    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. Jonathan Underwood
    Replies:
    2
    Views:
    640
    Simon Biber
    Aug 13, 2003
  2. MackS
    Replies:
    11
    Views:
    645
    Richard Bos
    Jan 31, 2005
  3. Jim Langston
    Replies:
    4
    Views:
    557
    Earl Purple
    Nov 14, 2006
  4. Replies:
    4
    Views:
    678
  5. Mister B
    Replies:
    8
    Views:
    554
    Nick Keighley
    Aug 26, 2010
Loading...

Share This Page