0

Win7 Cygwin

This the first time I've used templates & containers. I don't understand the errors. To my (naive) way of looking at things, I have defined an allocator (_Alloc) and a typdef (allocator_Type). The messages appear to be saying that I haven't done my homework properly. I have no clue as to what to do.

The code is:

template<typename T, typename _Alloc = std::allocator<T>>
class Array : public vector<T, _Alloc> {
   public:
      typedef T         value_type;
      typedef _Alloc    allocator_Type;
   private:
   int compar (const void* p1, const void* p2) { T v1 = (T)*p1;
                                                 T v2 = (T)*p2;
                                                 return (v1 < v2)? -1: (v1 > v2)? 1: 0;   }
   public:
   explicit Array (const allocator_Type& alloc = allocator_type()) : vector<T, _Alloc>(alloc)    { };
   explicit Array (size_t n)                                       : vector<T, _Alloc>(n)        { };
            Array (size_t n, const T& val,
                    const allocator_type& alloc = allocator_type()): vector<T, _Alloc>(n, val, alloc) { };
};

The error messsages are:

main.cpp:31:27: error: 'allocator_type' does not name a type
                     const allocator_type& alloc = allocator_type()): vector<T, _Alloc>(n, val, alloc) { };
                           ^
main.cpp:31:27: note: (perhaps 'typename std::vector<_Tp, _Alloc>::allocator_type' was intended)
main.cpp:31:66: warning: ISO C++ forbids declaration of 'alloc' with no type [-fpermissive]
                     const allocator_type& alloc = allocator_type()): vector<T, _Alloc>(n, val, alloc) { };
                                                                  ^
main.cpp:28:65: warning: there are no arguments to 'allocator_type' that depend on a template parameter, so a declaration of 'allocator_type' must be available [-fpermissive]
    explicit Array (const allocator_Type& alloc = allocator_type()) : vector<T, _Alloc>(alloc)    { };
                                                                 ^
main.cpp:31:66: warning: there are no arguments to 'allocator_type' that depend on a template parameter, so a declaration of 'allocator_type' must be available [-fpermissive]
                     const allocator_type& alloc = allocator_type()): vector<T, _Alloc>(n, val, alloc) { };
                                                                  ^
lostbits
  • 928
  • 1
  • 9
  • 23
  • 10
    To note, `std::vector`'s destructor is not declared virtual and thus should not be used as a base class. – Borgleader Oct 30 '14 at 14:28
  • 7
    "How do you use vector as a base class" - You **do not**. `std::vector` was designed to be encapsulated, not inherited. – utnapistim Oct 30 '14 at 14:30
  • 2
    `typedef _Alloc allocator_Type` is the actual name. You wrote `allocator_type` with a lowercase t. – David G Oct 30 '14 at 14:31
  • Borgleader & utnapistim: sigh. All hope is lost. Thanks! – lostbits Oct 30 '14 at 14:34
  • 1
    @ArthurSchwarez Don't get scared by the dogmatists. Nothing bad will happen if you derive from a container. Just don't delete through a pointer to the base... – jrok Oct 30 '14 at 14:36
  • to 0x499602D2: it appears that fixing the spelling cleared the errors. How do I resolve the issue that vector is not inheritable (Borgleader & utnapistim) and the fact that I have no errors? Can I use vector as a base class? – lostbits Oct 30 '14 at 14:41
  • @ArthurSchwarez - What is it that your `Array` class can do that vector cannot do? Also, why are you resorting to C-casts, void pointers, i.e. basically `C` style for `compare`? – PaulMcKenzie Oct 30 '14 at 14:53
  • 1
    @ArthurSchwarez They said *should not*...not *could not*. See ["thou shalt not inherit from std::vector"](http://stackoverflow.com/questions/4353203/thou-shalt-not-inherit-from-stdvector) for various opinions. People who've thought of "cool features" to add to vector like limiting it to a maximum size find that you have to be very careful to make sure all modifying routines get overridden to add the check. If you depend on that then suddenly you can't just switch to another collection. It's usually the wrong granularity vs. using standard containers within class design matching your domain. – HostileFork says dont trust SE Oct 30 '14 at 14:59
  • `_Alloc` is not a name that you are allowed to use in your code, it's strictly reserved for the implementation (e.g. `std::vector` can use it.). Simplified rule: avoid all leading underscores and all double underscores. – MSalters Oct 30 '14 at 17:03
  • @jrok deleting via base pointer is only one potential problem. You can also get slicing issues. That said if you're careful you'll be fine, and C++ generally requires you to be careful anyway. – Mark Ransom Oct 30 '14 at 21:23
  • P.S. As the error message indicates, you need to use `typename` before a template type name under certain circumstances. – Mark Ransom Oct 30 '14 at 21:25

2 Answers2

1

This has been stated in comments but not posted as an answer yet: you don't.

The standard library containers are not supposed to be used as (public) base classes. They are non-polymorphic, so you can't pass an object derived from one safely to any function which expects a pointer or reference to the container.

You could , in theory, use a standard container as private base class. This has the same semantics as a private member variable, but it would make your code a lot easier to follow for others if you just used a private member variable.

M.M
  • 138,810
  • 21
  • 208
  • 365
0

First - you have a typo: uppercase T in allocator_Type and lowercase in const allocator_Type& alloc = allocator_type(). Second - std::vector destructor is not virtual, hence you really should not derive from it unless you never cast and delete via base class.

krojew
  • 1,297
  • 15
  • 38