I am working on a project and I have run into an issue with populating a 3d vector array. When I try to complile the code below I get the following error.

no matching function for call to ‘std::vector<std::vector<std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >

I am not sure where I went wrong but any help with this would be greatly appreciated.

Here is my current code implementation.

vector<vector<vector<string> > > vec;
	

	for (int i = 0; i < 3; i++) {
	    vector<string> row;
	    
	    row.push_back("Row");	    
	    for(int j = 0; j < 5; j++){
	    	vector<string>col;
	    	col.push_back("\t\t COL");
	    	vec.push_back(col);
	    }
	    vec.push_back(vec);
	}
	
	for(int k = 0; k < vec.size(); k++){
		for(int l = 0; l < vec[k].size(); l++){
			cout <<  vec[k][l] << endl;
		}
	}

Recommended Answers

All 6 Replies

First, please please look at boost::multi_array or similar structures.
This is were the vector formalism really doesn't do anyone any favors.
http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/index.html

Next row can only have a vector<vector<string> > pushed back to it. col is a vector<std::string>. So that doesnt work.
You seem to be using it as a vector<vector<string> > so I would write

vector<vector<string> > vec;

  char Uletters[]="ABCDE";
  char Lletters[]="abcde";
  for (int i = 0; i < 3; i++) 
    {
      vec.push_back(vector<string>());
      for(int j = 0; j < 5; j++)
        {
	  vec[i].push_back("Item");
	  vec[i][j]+=Uletters[i];
	  vec[i][j]+=Lletters[j];
	}
    }
  for(unsigned int i=0;i<vec.size();i++)
    for(unsigned int j=0;j<vec[i].size();j++)
       cout<<"Vec "<<i<<" "<<j<<" == "<<vec[i][j]<<endl;

Note that you take the size of an indexed vector item in the loop vec[i] Finally, if you really want a 3D array (or tensor) then not a problem, the code extends to this.

vector<vector<vector<string> > > vec;

  char Uletters[]="ABCDE";
  char Lletters[]="abcde";
  for (int i = 0; i < 3; i++) 
    {
      vec.push_back(vector<vector<string> >());
      for(int j=0;j<2;j++)
        {
	  vec[i].push_back(vector<string>());
	  for(int k = 0; k < 5; k++)
	    {
	      vec[i][j].push_back("Item");
	      vec[i][j][k]+=Uletters[i];
	      vec[i][j][k]+=Lletters[j];
	      vec[i][j][k]+=Lletters[k];
	    }
	}
    }
  for(unsigned int i=0;i<vec.size();i++)
    for(unsigned int j=0;j<vec[i].size();j++)
      for(unsigned int k=0;k<vec[i][j].size();k++)
	std::cout<<"Vec "<<i<<" "<<j<<" "<<k<<" == "<<vec[i][j][k]<<std::endl;

Bit ugly but that is what you get for using such a construct.
See the boost or one of the many tensor classes available should you wish to change it. (The main advantage of this is that the tensor can be completely ragged e.g. the second row can have 6 items and the third row have 2. But most tenor/array classes require a constant inner count.

[Expert note: I didn't want to use stringstream here, because the questioner hadn't introduced them. ]

After looking at your example and trying it on my own, I was able to get the functionality that I was looking for by using a 2d vector array in my test project.

Just to add a little insight as to what I am trying to accomplish. Below is a text view of what the output array would be.

Resource : 0
	Class: 0
	Class: 1
	Class: 2
Resource : 1
	Class: 0
	Class: 1
Resource : 2
	Class: 0
	Class: 1

How ever, when I port the code into my actual project, I get to a point and then get a SegFault. The output from strace doesn't tell me a whole lot.

--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++

I know what the offending line is, just not sure what to do about it.

Here is an excert from my code. The offending line is vec[k][j]+=j;

MetadataResourceList::iterator i;
        int k = 0;        
        for (i = resources.begin(); i != resources.end(); i++)
        {                   
            MetadataResource * resource = *i;
            
            string resourceName = resource->GetResourceID();
               
            MetadataClassList classes =	
                metadata->GetAllClasses(resourceName);
            
            vec.push_back(vector<string>());
            vec[k].push_back(resourceName);
            MetadataClassList::iterator i;
            int j = 0;
            for (i = classes.begin(); i != classes.end(); i++)
            {
                 MetadataClass * aClass = *i;
                 cout << "Resource name: " << resourceName << " ["
                      << resource->GetStandardName() << "]" << endl;
                 cout << "Class name: " << aClass->GetClassName() << " ["
                      << aClass->GetStandardName() << "]" << endl;
                 cout << endl;
                 
                 vec[k][j]+=j;  // Error is caused here.
              j++;
            }
            k++;            
        }

Well you are pushing back an integer and j is zero and that is interesting :). It does work on my linux machine.

Additionally, if j gets bigger than 255 things can go badly wrong as well.

Both of these behaviour points are implementation specific. (I think)

I fixed the issue with the seg fault. I did forget to re-implement the check to make sure that the aClass->GetStandardName() string was not null.

Right now this is the output that I get from the working code.

Vec 0 0 == ActiveAgent
Vec 0 1 == Agent
Vec 1 0 == Agent
Vec 1 1 == Agent
Vec 2 0 == Office
Vec 2 1 == Office
Vec 3 0 == OpenHouse
Vec 4 0 == Property
Vec 4 1 == ResidentialProperty
Vec 4 2 == LotsAndLand
Vec 4 3 == MultiFamily
Vec 5 0 == Tour

How ever this still isn't exactly what I am trying to do. In the output from above, at lets say vec[4][0] the result is Property. Instead of being a child of the parent array. I need to make this a parent. So that if I used vec[4][0] I would get ResidentialProperty and if I used vec[4] I would get Property. I am not entirely sure if this is possible with the current code that I am using.

Every vec[x][0] index is the parent data that I need to work with first.

You have used an array structure. It sounds like you want to use a tree.
Obviously, everyone who has read Knuth [interestingly only in volume 4] :) , knows that an array can be used to represent a tree. Depending on what you want to do that might be the way forward. (Simple check down the array).

However, I think that you might need a tree. Since you look like you are going to want to use the properties of a tree more than just getting an output.

Sorry for the over abundance of questions. Coming from AS3 to c++ is a rather odd change, but an enjoyable one. I will look into using a tree.

Thank you for your help.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.