Struct with vector, error C2679.

Hello,
I would like to display the data which is in my vector. When Im trying to compile my program an error like this apears:

error C2679: binary '[' : no operator found which takes a right-hand operand of type 'std::_Vector_iterator<_Myvec>' (or there is no acceptable conversion)
with
1> [
1> _Myvec=std::_Vector_val<Krolowie,std::allocator<Krolowie>>
1> ]
1> C:\Program Files\Microsoft Visual Studio 10.0\VC\include\vector(911): could be 'const Krolowie &std::vector<_Ty>::operator [](unsigned int) const'
1> with
1> [
1> _Ty=Krolowie
1> ]
1> C:\Program Files\Microsoft Visual Studio 10.0\VC\include\vector(927): or 'Krolowie &std::vector<_Ty>::operator [](unsigned int)'
1> with
1> [
1> _Ty=Krolowie
1> ]
1> while trying to match the argument list '(std::vector<_Ty>, std::_Vector_iterator<_Myvec>)'
1> with
1> [
1> _Ty=Krolowie
1> ]
1> and
1> [
1> _Myvec=std::_Vector_val<Krolowie,std::allocator<Krolowie>>
1> ]

Most crucial elements of my code:
1
2
3
4
5
6
7
8
9
10
11
struct Krolowie
{...};
std::vector<Krolowie> Wektorek;
(...)
void ShowAll()
{
	for( auto y = Wektorek.begin(); y != Wektorek.end(); y++ )
	{
		std::cout << Wektorek[y] << std::endl;//error in this line
	}
}


I would be very thankful for help. :)
*y, not Wektorek[y].
The error message has:
a right-hand operand of type 'std::_Vector_iterator<_Myvec>'

and
could be 'const Krolowie &std::vector<_Ty>::operator [](unsigned int) const'

'Wektorek' is a vector<Krolowie> and vectors do have an operator[]. Like the message says, that operator expects unsigned int. There are no overloads.

'y' has type of ... whatever vector::begin() returns. That happens to be an iterator to vector. Rightly so, the error message says '_Vector_iterator'.

You can use iterators or you can use [] (with indices).

You could use range-based for loop too:
1
2
3
for ( const auto & kr : Wektorek ) {
  std::cout << kr << '\n';
}

To be honest I dont really understand ;( When I replaced Wektorek[y] with *y I recived almost identical error. When I tried to use range-based loop I recieve many errors:
1>Poczet.cpp(96): error C2143: syntax error : missing ',' before ':'
1>Poczet.cpp(96): error C2530: 'kr' : references must be initialized
1>Poczet.cpp(96): error C3531: 'kr': a symbol whose type contains 'auto' must have an initializer
1>Poczet.cpp(97): error C2143: syntax error : missing ';' before '{'
Is it possible that my compiler is "to old" for that?
When I replaced Wektorek[y] with *y I recived almost identical error.
You probably didn't define an overload for operator<<(std::ostream &, Krolowie &). You can't just send any type to an output stream.
Yes. Range-based for-loop syntax is in C++11 and not all compilers support that. (MSVC 2012 and 2013 do document it.)
And how do I define an overload for operator<< ? :(
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
#include <iostream>
#include <string>
#include <ostream>		
#include <istream>

struct Student{
	std::string name;
	int ID = 0;
        // operator overloading
	friend std::istream &operator>> (std::istream &in, Student &cStudent);
	friend std::ostream &operator<< (std::ostream &out, Student &cStudent);
};
// overload >>
std::istream &operator>> (std::istream &in, Student &cStudent)
{
	in >> cStudent.name;
	in >> cStudent.ID;
	return in;
}
// overload << 
std::ostream &operator<< (std::ostream &out, Student &cStudent)
{
	out << cStudent.name << "\n\t" << cStudent.ID << "\n";
	return out;
}

int main()
{
	Student data;
	std::cin >> data;
	
	std::cout << "You entered:\n";
	std::cout << data;    
	
	return 0;
}
James
2859324
You entered:
James
	2859324
Isnt there any easier way to do this? It looks a bit complicated. Isnt it possible to i/o data like std::cout << Vector[y].ID << Vector[y].Name instead of *y? I used that operator overload and output seems to work but there is an error with input :( What I got:
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
(...)
std::ostream &operator<< (std::ostream &out, Krolowie &cKrolowie)
{
	out << cKrolowie.Imie << "\n\t" << cKrolowie.Urodzenie << "\n\t" << cKrolowie.RokRopoczecia << "\n\t" << cKrolowie.RokZakonczenia << "\n\t"  << cKrolowie.RokSmierci << "\n";
	return out;
}
std::istream &operator>> (std::istream &in, Krolowie &cKrolowie)
{
	in >> cKrolowie.Imie;
	in >> cKrolowie.Urodzenie;
	in >> cKrolowie.RokRopoczecia;
	in >> cKrolowie.RokZakonczenia;
	in >> cKrolowie.RokSmierci;
	return in;
}
(...)
void Wczytaj()
{
	std::cout << "Podaj nazwe pliku z ktorego chcesz wczytac dane (uwaga plik musi znajdowac sie w folderze z programem): " << std::endl;
	std::string plik;
	std::cin >> plik;
	plik = plik + ".txt";
	std::ifstream in( plik );
	if ( in.good() )
	{
		for( auto y = Wektorek.begin(); y != Wektorek.end(); y++ )
		{
			//fin >> Wektorek[y].Imie >> Wektorek[y].Urodzenie >> Wektorek[y].RokRozpoczecia >> Wektorek[y].RokZakonczenia >> Wektorek[y].RokSmierci;
			in >> *y >> std::endl;
		}
	}
	else
	{
		std::cout << "Nie istnieje taki plik. \n";
	}
}

The error:
1>Poczet.cpp(141): error C2678: binary '<<' : no operator found which takes a left-hand operand of type 'std::ifstream' (or there is no acceptable conversion)
1> Poczet.cpp(18): could be 'std::ostream &operator <<(std::ostream &,Krolowie &)'
1> while trying to match the argument list '(std::ifstream, Krolowie)'

Sorry for other language than English. If its annoying Ill change it, but I think it doesnt really matter.
Last edited on
Isnt there any easier way to do this? It looks a bit complicated. Isnt it possible to i/o data like std::cout << Vector[y].ID << Vector[y].Name instead of *y?
Yes:
1
2
3
4
5
		for( auto y = Wektorek.begin(); y != Wektorek.end(); y++ )
		{
			in >> y->Imie >> y->Urodzenie >> y->RokRozpoczecia >> y->RokZakonczenia >> y->RokSmierci;
			// in >> *y >> std::endl;
		}
I used your code and I got another problem. It compiled, yay! But it doesnt really work :(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void Wczytaj()
{
	std::cout << "Podaj nazwe pliku z ktorego chcesz wczytac dane (uwaga plik musi znajdowac sie w folderze z programem): " << std::endl;
	std::string plik;
	std::cin >> plik;
	plik = plik + ".txt";
	std::ifstream fin( plik );
	if ( fin.good() )
	{
		for( auto y = Wektorek.begin(); y != Wektorek.end(); y++ )
		{
			fin >> y->Imie >> y->Urodzenie >> y->RokRopoczecia >> y->RokZakonczenia >> y->RokSmierci;
			std::cout << "Cant see that" << std::endl;
		}
		std::cout << "Can see this" << std::endl;
	}
	else
	{
		std::cout << "Nie istnieje taki plik. \n";
	}
}

It looks like it doesnt get into the for loop. I got this vector as global variable. But by default it has length of 0 yes? So I guess I should add at the beginning of this function something that will make some space in the vector. Maybe I should use .push_back inside this loop?
Last edited on
Here is some sample code I have that may help you (lines 40 - 46), but included full code and file for you to experiment with if you want.
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
#include <iostream>		
#include <string>		
#include <vector>		
#include <fstream>		
#include <cstdlib>		
#include <iomanip>		

using namespace std;

struct Spells{
      string name;
      int cost = 0;
      friend ostream &operator<< (ostream &out, Spells &cSpells);
      friend istream &operator>> (istream &in, Spells &cSpells);
};

ostream &operator<< (ostream &out, Spells &cSpells)
{
	out << setw(20) << left << cSpells.name << " :: " << setw(20) << right << cSpells.cost << endl;
	return out;
}

istream &operator>> (istream &in, Spells &cSpells)
{
	getline(in, cSpells.name);
	in >> cSpells.cost;
	return in;
}

int main(int argc, char **argv)
{
      vector <Spells> spellList;
      Spells *data = new Spells[50];
      ifstream spellFile("spells");
      if(!spellFile){
		  cout << "Can't open file.\n";
      }
      int index = 0;
      while(!spellFile.eof())
      {
		  spellFile >> data[index];
		  spellList.push_back(data[index]);
		  spellFile.ignore(1, '\n');
		  index++;
		  if(spellFile.eof())break;
      }
      cout << setw(22) << left << "Spell Name" << setw(22) << right << "Cost in Gold" << endl;
      cout << setw(44) << setfill('=') << "" << setfill(' ') << endl;
      for (unsigned count = 0; count < spellList.size() - 1; count++)
      {
		  cout << spellList[count];
      }
	  
      delete[] data;
      spellFile.close();
      
      return 0;
}
Spell Name                      Cost in Gold
============================================
Thunder              ::                  100
Fire                 ::                  100
Ice                  ::                  100
Water                ::                  100
Heal                 ::                  100
Thunder II           ::                  500
Fire II              ::                  500
Ice II               ::                  500
Water II             ::                  500
Heal II              ::                  500
Thunder III          ::                 1000
Fire III             ::                 1000
Ice III              ::                 1000
Water III            ::                 1000
Heal III             ::                 1000
Ultima               ::                 2000
Meteor               ::                 2000

spells (file)

Thunder
100
Fire
100
Ice
100
Water
100
Heal
100
Thunder II
500
Fire II
500
Ice II
500
Water II
500
Heal II
500
Thunder III
1000
Fire III
1000
Ice III
1000
Water III
1000
Heal III
1000
Ultima
2000
Meteor
2000
Last edited on
@BHX Specter
Using eof() like you did is a typical beginner error. You shouldn't use ignore like you did. Better like so:
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
istream &operator>> (istream &in, Spells &cSpells)
{
	getline(in, cSpells.name);
	in >> cSpells.cost;
	in.ignore(1, '\n'); // Note: Better place
	return in;
}

int main(int argc, char **argv)
{
      vector <Spells> spellList;
      Spells *data = new Spells[50];
      ifstream spellFile("spells");
      if(!spellFile){
		  cout << "Can't open file.\n";
      }
      int index = 0;
      Spells data; // Note
      while(spellFile >> data)
      {
		  spellFile >> data[index];
		  spellList.push_back(data[index]);
		  spellFile.ignore(1, '\n');
		  index++;
		  if(spellFile.eof())break;
      }


@Furjoza
Similar in your case:
1
2
3
4
5
6
7
8
9
Krolowie data;
	while ( fin >> data.Imie >> data.Urodzenie >> data.RokRopoczecia >> data.RokZakonczenia >> data.RokSmierci )
	{
		Wektorek.push_back(data);
	}
	if( !fin.eof() )
	{
		std::cout << "Nie istnieje taki plik. \n";
	}
But overloading the operator<< and operator>> for Krolowie seems not the worst idea ever
Last edited on
@coder777
Yeah, I should have took more time to tweak the code since I was offering it as an example. The original code was for me to learn using new and delete when I was playing with an terminal RPG when I first started programming. The operator overloading, and vector wasn't in the original code so I added them real fast and copy/pasted chunks, but should have removed the obsolete code and double checked the logic before submitting it. As for the 'beginner error', that is the first time in all these years I've seen anything about that as I've always done !infile.eof() or infile.eof().

[EDIT] Forgot the second variant infile.eof().

[EDIT.:2:.] I see what you mean, an acquaintance pointed it out to me. What you call a "beginner error" is actually a common error because programmers sometimes forget that in order to use infile.eof(), as I intended there, you MUST read in from infile at least once before checking it for eof(). Another way to fix it (rather than doing while(infile >> data) as you did) you can either add two needless calls to infile >> data; and vector.push_back(data); before the while() or simply switch my original while to a do{}while(); so that it at least read in from infile once.
Last edited on
Thanks for your replies guys. It works :D I made it the way cover777 has shown ;)
Topic archived. No new replies allowed.