Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Not able to overload existing std::vector functions

Tags:

c++

stl

vector

I am doing a POC implementation and as per requirement I need to extend std::vector insert API which would take only single parameter (value to be inserted) and internally the code would add this in the end of container.

I created a custom class (ValVector) derived from std::vector and defined a custom Insert API which accepts single parameter but while compiling it throws error.

Below is the snippet code with error message:

#include <iostream>
#include <vector>

using namespace std; 

typedef bool BOOL;

template<class T, class Allocator = allocator<T>>

class ValVector : public std::vector<T, Allocator> {

  public: 
    BOOL insert(const T& elem) { return (this->insert(this->end(),elem)!=this->end()); }
 };

int main ()
{
  std::vector<int> myvector (3,100);
  std::vector<int>::iterator it;

  myvector.push_back (200 );

  ValVector<int> mKeyAr;

  mKeyAr.insert(10); // 

 std::cout << "myvector contains:";
  for (auto it=mKeyAr.begin(); it<mKeyAr.end(); it++)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

Error Message:

In instantiation of 'BOOL ValVector<T, Allocator>::insert(const T&) [with T = int; Allocator = std::allocator<int>; BOOL = bool]': 
23:19: required from here 
11:72: error: no matching function for call to 'ValVector<int>::insert(std::vector<int>::iterator, const int&)' 
11:72: note: candidate is: 
11:10: note: BOOL ValVector<T, Allocator>::insert(const T&) [with T = int; Allocator = std::allocator<int>; BOOL = bool] 
11:10: note: candidate expects 1 argument, 2 provided In member function 'BOOL ValVector<T, Allocator>::insert(const T&) [with T = int; Allocator = std::allocator<int>; BOOL = bool]': 
11:88: warning: control reaches end of non-void function [-Wreturn-type] 
like image 875
Ashwan Avatar asked Jul 08 '15 11:07

Ashwan


2 Answers

To address your actual question: declaring a function in a class hides all inherited functions of the same name in that class. In other words, because ValVector has a function named insert, the inherited std::vector::insert is no longer visible in it. Probably the best way to solve this is to bring the inherited insert back to scope with a using declaration:

template<class T, class Allocator = allocator<T>>
class ValVector : public std::vector<T, Allocator> {

  public: 
    using std::vector<T, Allocator>::insert;

    BOOL insert(const T& elem) { return (this->insert(this->end(),elem)!=this->end()); }
};

However, I have a comment to make. I think your approach is wrong. std containers are not intended for public inheritance; if nothing else, they have no virtual destructor and no protected members. You'd be better off providing a free function, which could then be used with any std::vector, not just your type:

template <class T, class A>
BOOL insert(std::vector<T, A> &vec, const T &val)
{
  return vec.insert(vec.end(), val) != vec.end();
}

Or make it a bit more generic to work with any container:

temlate <class C, class E>
BOOL insert(C &cont, const E &val)
{
  return cont.insert(cont.end(), val) != cont.end();
}
like image 126
Angew is no longer proud of SO Avatar answered Nov 15 '22 07:11

Angew is no longer proud of SO


When you make your own insert member function for something which isn't virtual you hide all the same name functions from higher up (I think it's called shadowing). You are now trying to call a function which is no longer visible.

Is there a good reason not to just make a separate function which does what you need, or do you have to derive this from vector? Nothing you are doing requires access to protected data or functions...

// from
vector.insert(data);
// to
insert_poc(vector, data);
like image 23
Andy Newman Avatar answered Nov 15 '22 05:11

Andy Newman