C++ error: class Property<int> has no member named ‘push_back’

So I have a .dat file below filled with records that I'm trying to read and compute statistics for:
1
2
3
4
5
6
	2000 AB Bachelor's
	2005 DE Bachelor's
	2010 CA Bachelor's
	2015 AB Masters's
        2015 SK Masters's
        2000 MB Bachelor's

In the createReport class, I have declared an STL vector of record pointers called collection which will store all the data from this file.

I also have a collection of Property object pointers called years. Each Property object stores a collection that is a subset of the records in the primary data collection, and each element inside this collection will hold the records for one specific value of a property. In this case, the property for this collection represented in the data is the year, because every record represents data for a specific year.

Based on the data above, the data contains statistics for only four different years (2000, 2005, 2010, and 2015), so the years collection will contain exactly four elements, one for each year; the first element of the years collection will contain all the records for the year 2000; the second element will contain those for the year 2005, and so on for the years 2010 and 2015.

I'm trying to implement a populate() function in createReport.cc that populates the years collection to complete the task above but I keep getting the error:

1
2
3
	createReport.cc:50:27: error: ‘class Property<int>’ has no member named ‘push_back’
	   years[r->getYear()]->push_back(r);
							   ^~~~~~~~~


I have not finished implementing the Property class but I thought push_back() was a built-in function so I don't understand why it's saying this member hasn't been declared. I should mention Property.h is a class template so there is no source file for it. I would appreciate any help!

EDIT: In the event that I can't use push_back(), how else would I be able to populate the years collection?

Record.cc
1
2
3
4
5
6
7
8
9
10
11
12
	#include <iostream>
	#include <string>
	using namespace std;
	#include "Record.h"

	Record::Record(int i1, string s1, string s2) : year(i1), province(s1), degree(s2), gender(s3){}

	Record::~Record(){}

	int Record::getYear(){
		return year;
	}

createReport.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
	#ifndef CREATEREPORT_H
	#define CREATEREPORT_H

	#include <iostream>
	#include <fstream>
	#include <string>
	#include <vector>
	#include <iterator>
	#include <algorithm>
	#include <cstdlib>

	#include "Record.h"
	#include "Property.h"

	class createReport{
	  public:
		createReport();
		static void populate();
	  
	  protected:
		static vector<Record*> collection;
		static std::vector<Property<int>*> years;   	
	  
	};
	#endif 

createReport.cc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
	#include <iostream>
	using namespace std;
	#include <string>

	#include "createReport.h"

	createReport::createReport(){ 
	}

	void createReport::populate(){
		for(Record* r : collection) { 
			years[r->getYear()]->push_back(r); 
	  }
	}


Property.h

1
2
3
4
5
6
7
8
9
10
	#include <iostream>
	using namespace std;
	#include <cstdlib>

	template <class T>

	class Property{
		public:
		private:
	};
Last edited on
Also note: I'm not allowed to use stl:map, nothing else from the STL is allowed except STL vector.

To help illustrate what I'm trying to do in populate(), the years collection should have 4 elements which is one for each year - 2000, 2005, 2010, 2015.

Each element contains the records for each year so for 2000 there are 2 records which are the lines "2000 AB Bachelor's" and "2000 MB Bachelor's", 2005 has 1 record, 2010 has 1 record, 2015 has 2 records. I also have int, string, and another string variable in Record.cc to represent the year, province, and degree aspect of each record.
Last edited on
Start with the smallest possible idea in a single source file to prototype your ideas.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include<iostream>
#include<vector>
using namespace std;

class Record {
public:
  Record(int year) : m_year(year){}
  int getYear(void) const {
    return m_year;
  }
private:
  int m_year;
};

template <class T>
class Property {
public:
private:
};

class createReport{
public:
  createReport();
  void populate();
private:
  vector<Record> collection;
  vector<Property<int>> years;
};

createReport::createReport(){
}

void createReport::populate(){
  for(Record r : collection) {
    Property<int> f;
    // now what?
    // convert a Record to a Property

    //you needed some kind of vector<vector> here to make this work
    //years[r.getYear()].push_back(f);

    years.push_back(f);
  }
}


Snippets of a broken multi source project won't help.
> error: class Property<int> has no member named ‘push_back’
> I have not finished implementing the Property class but I thought push_back() was a built-in function

Your property class is empty; it does not have any members as yet.
Once you add a vector member to your property class, you can use push_back() on the vector.


Here is a minimal scaled down example of what (I think) you are expected to do:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <iostream>
#include <string>
#include <vector>

struct record
{
    int year ;
    std::string province ;
    std::string degree ;
    std::string gender ;
};

// a property maps the key to a collection of pointers to records
template < typename KEY > struct property
{
    KEY key ;
    std::vector< const record* > recs ;
};

// just a collection of properties
// map etc. are not allowed, so we use vectors everywhere
template < typename KEY > struct property_collection
{
    std::vector< property<KEY> > items ;

    // add this record with this key to the collection
    void add( const KEY& key, const record* r )
    {
        if( r == nullptr ) return ;

        // if a property with this key is found, add the record to its vector and return
        // we are not keeping the keys in sorted order; so a simple sequential search
        for( auto& prop : items ) if( prop.key == key ) return prop.recs.push_back(r) ;

        // we did not find a property with this key;
        // so we create a new one with this key and just this one record in the vector
        items.push_back( { key, {r} } ) ;
    }
};

// a namespace instead of a class with all static members
namespace report_gen
{
    std::vector< const record* > records ;

    property_collection<int> years ;
    property_collection<std::string> provinces ;
    // etc

    void populate()
    {
        for( const record* r : records ) if(r) // for all non-null pointers in records
        {
            years.add( r->year, r ) ; // add to the appropriate years property
            provinces.add( r->province, r ) ; // add to the appropriate provinces property
            // etc.
        }
    }
}

int main()
{
    // create a set of records for testing
    // for this simple test, we use an array to hold the records by value because pointers
    // to items in a vector may get invalidated if the vector is modified
    const record data[]
    {
        { 2000, "AB", "Bachelor's", "M" },
        { 2005, "DE", "Bachelor's", "F" },
        { 2010, "CA", "Bachelor's", "F" },
        { 2015, "AB", "Masters's", "M" },
        { 2000, "AB", "Bachelor's", "M" },
        { 2005, "DE", "Master's", "F" },
        { 2010, "DE", "Master's", "U" },
        { 2015, "AB", "Masters's", "M" },
        { 2000, "AB", "Bachelor's", "M" },
        { 2005, "DE", "Bachelor's", "F" },
        { 2010, "AB", "Doctorate", "F" },
        { 2015, "AB", "Masters's", "M" },
        { 2010, "CA", "Diploma", "M" },
    };

    // add pointers to the records to report_gen
    for( const record& rec : data ) report_gen::records.push_back( std::addressof(rec) ) ;

    // populate the property collections in report_gen
    report_gen::populate() ;

    // generate a report: list of all records for the year 2010
    // note that the actual reports to be generated would be members of report_gen. 
    for( const auto& prop : report_gen::years.items )
    {
        if( prop.key == 2010 ) // if it is for year 2010
        {
            std::cout << "year 2010: found " << prop.recs.size() << " records\n-----------\n" ;
            for( const record* r : prop.recs ) // print all the records in the vector
                std::cout << r->year << ' ' << r->province << ' ' << r->degree << ' ' << r->gender << '\n' ;
        }
    }

    // generate another sample report: count of students with gender F in province DE
    int n = 0 ;
    for( const auto& prop : report_gen::provinces.items )
    {
        if( prop.key == "DE" ) // if it is for the province DE
            for( const record* r : prop.recs ) n += r->gender == "F" ;
    }
    std::cout << "\nthere are " << n << " records with gender == \"F\" in province \"DE\"\n" ;
}


http://coliru.stacked-crooked.com/a/5c218f33fdd20df2
Last edited on
Hello marystew,


I have not finished implementing the Property class but I thought push_back() was a built-in function


The "push_back()" function is not built int the whole of the IDE or compiler, but a member function of, in this case, the vector class. It can also be found in other classes.

As JLBorges has pointed out first you have to create a vector, (std::vector vectorName;), before you can use vectorName.push_back(something);. Then it should work for you.

Andy
Topic archived. No new replies allowed.