Accessing variables in a template that is a vector

2019-09-19 14:40发布

问题:

How do I access the variables itemtype and total within the increment function? The code I have below gives me errors as follows

Counter2.h: In member function ‘int Counter::increment(T)’:

Counter2.h:28:31: error: ‘itemtype’ was not declared in this scope

Counter2.h:36:22: error: ‘itemtype’ was not declared in this scope

Counter2.h:36:39: error: ‘total’ was not declared in this scope

I must be able to use the command Counter<T> counter; where T can be any type, such as string and counter.increment()

#include<string>
//#include<cstdlib>
#include<vector>

using std::vector;
using std::string;

template<class T>
class Record{
   public:
      T itemtype;
      int total;   
};

template<class T>
class Counter{
      vector< Record<T> > data;
   public:
      int increment(T item);
      int count(T item);
      void printSummary();
};

template<class T>
int Counter <T> :: increment(T item){
   bool check = false;

   for(int i=0; i < data.size(itemtype); i++){
      if(data[i].itemtype == item){
         data[i].total++;
         bool check = true;
         break;
      }
   }
   if(check == false){
      data.push_back(itemtype = item, total = 1);
   }
}

int main(){

   Counter<string> counter;   

   counter.increment("orange");
   counter.increment("orange");

   return 0;
}

回答1:

In line for(int i=0; i < data.size(itemtype); i++){

will be: for(int i=0; i < data.size(); i++){

And data.push_back(itemtype = item, total = 1); can be:

  1. data.push_back({item, 1}); // by using initializer list ; C++11

  2. or,

    Record r; 
    r.itemtype = item; 
    r.total = 1;
    data.push_back(r);
    

You can look at : http://www.cplusplus.com/reference/vector/vector/ to know about std::vector.



回答2:

I'm not too sure I understand what you're after here, though for a start you're trying to access private members of class Record. You could make record a struct (public by default), or provide getters/setters or alternatively add:

friend class Counter;

to Record so that Counter can access its private members.



回答3:

You can make Record a private structur inside Counter. That will not expose it implementation. You need to change also how you acces data. It is a vector of Record, not a Record. Something like:

template<class T>
class Counter
{
    struct Record{   T itemtype;    int total;      };
    vector< Record > data;
   public:
      int increment(const T& item);
      int count(const T& item);
      void printSummary();
};
template<class T>
int Counter <T> :: increment(const T& item)
{
   auto i=data.begin();
   i= find(i,data.end(),[&item](const Record& r)
                        {return item==r.itemtype;});
   if (i!=data.end())
       return ++(i->total);
   data.push_back({item, 1}); 
   return 1; 
 }

If you dont like the lambda fun:

template<class T>
int Counter <T> :: increment(const T& item)
{
    for(int i=0; i < data.size(); ++i)
      if(data[i].itemtype == item)
         return ++(data[i].total);
    data.push_back({item, 1}); 
    return 1;
}

But i think what you actually need is a multiset (if you dont care about the order). Something like this:

template<class T>
class Counter
{
    std::multiset <T> data;
   public:
      int increment(T item);
      int count(T item);
      void printSummary();
};

template<class T>
int Counter <T> :: increment(T item)
{
   data.insert(item);
   return data.count(item);
}