I am trying to port my code from Win (VC6) to Linux (gcc 2.95).
I am getting a weired compilation error while using the at() function in STL's std::vector.
I want to use at() instead of [] because Mark Allen Weiss in his "Data Structures and Problem .. C++" claims the following::
Range checking can be done by using at; a.at(i) is the same as a[i], except that an error is signalled if i is out-of-bounds.
boundsMin is of type TVec3<double>;
vertices is of type std::vector<TVec3<double>>;
Note that the first and third lines use at(ii). the second line uses [ii];
error:::
--------
Box3D.cpp: In method `Box3D::Box3D(const Vec3DArray &)':
Box3D.cpp:53: no matching function for call to `vector<TVec3<double>,allocator<TVec3<double> > >::at (int &) const'
Box3D.cpp:55: no matching function for call to `vector<TVec3<double>,allocator<TVec3<double> > >::at (int &) const'
I want to clarify the following two points.
1. I don't understand what's wrong with the above code. It runs fine in VC6.
2. I gave only only one argument to at(), but the allocator<TVec3<double>> is automatically added by the compiler. What's going on there ?
Thanks.
Ragu
willchop
September 7th, 2002, 12:59 PM
Ragu,
What is the 'ii' variable? Looks like the compiler is tagging it as
a reference to an integer. If so, it can't find an overloaded
version of the .at(int &) function. It only has .at(size_type).
regards, willchop
ragunath
September 7th, 2002, 01:14 PM
willchop,
variable ii is an int.
Here's the full block of code.
Box3D::Box3D(const Vec3DArray &vertices)
{
Vec3D boundsMin(DBL_MAX,DBL_MAX,DBL_MAX),
boundsMax(-DBL_MAX, -DBL_MAX, -DBL_MAX);
int ii;
for (ii=0; ii < vertices.size(); ++ii)
{
boundsMin.x = my_min(boundsMin.x, vertices.at(ii).x);
boundsMin.y = my_min(boundsMin.y, vertices[ii].y);
boundsMin.z = my_min(boundsMin.z, vertices.at(ii).z);
Please note that I am getting an error only when i am using the at(ii). When I am using [ii], I am not getting any error.
(Sorry for not writing this clearly in my original post).
Thanks.
Ragu
willchop
September 7th, 2002, 01:24 PM
Are you calling the const version of at()? The second parameter
of my_min() would need to be a constant for the correct compile
time selection of 'const_reference at() const'.
regards, willchop
Graham
September 7th, 2002, 02:10 PM
It's definitely to with const. "vertices" is a reference to const, so it needs vector::at() const for it to work. I don't have my books with me to check if there is (or should be) a const version of at, but that's what it's complaining about.
willchop
September 7th, 2002, 02:16 PM
Graham,
I believe there is 2 versions of at(). One non-const version that
returns a reference and one const version that returns a const
reference.
regards, willchop
ragunath
September 7th, 2002, 02:22 PM
I am sorry. But I do not understand what you are talking about.
1. This is how my_max() and my_min() are defined.
double my_max(const double a, const double b)const
{ return ((a > b) ? a : b);};
double my_min(const double a, const double b)const
{ return ((a < b) ? a : b);};
2. This is how the function is defined. (implementation in the last post mesg.)
Box3D(const Vec3DArray &vertices);
3. This is how the code gets called (as posted before).
boundsMin.x = my_min(boundsMin.x, vertices.at(ii).x);
Can you please explain what I am doing wrong (and stupid) here.
Thanks.
Ragu
willchop
September 7th, 2002, 02:58 PM
Sorry, I don't have gcc here at home to test with. Does this code
compile in your gcc?
// header
template<class T> class TVec3
{
public:
TVec3() : x(0), y(0), z(0) {}
T x;
T y;
T z;
};
Originally posted by ragunath
I am sorry. But I do not understand what you are talking about.
1. This is how my_max() and my_min() are defined.
double my_max(const double a, const double b)const
{ return ((a > b) ? a : b);};
double my_min(const double a, const double b)const
{ return ((a < b) ? a : b);};
2. This is how the function is defined. (implementation in the last post mesg.)
Box3D(const Vec3DArray &vertices);
3. This is how the code gets called (as posted before).
boundsMin.x = my_min(boundsMin.x, vertices.at(ii).x);
Can you please explain what I am doing wrong (and stupid) here.
Thanks.
Ragu The errors are as Graham described. You passed a const vector. This means that within the function, you guarantee that the vector does not get modified. The at() function is not const, therefore you've violated the contract -- the vector can be modified by the at() function (even if it actually isn't modified by at()). You can easily determine whether at() is const by looking in the <vector> header file and see how at() is declared.
So either your at() function is not declared as const, or possibly, you have no at() function to begin with (which would make your STL implementation non-standard).
Regards,
Paul McKenzie
AnthonyMai
September 8th, 2002, 01:59 AM
Paul's speculation about constness being the cause of the problem is SURELY wrong, as any one using a bit of logic can see. The point is Paul's constness argument would apply equally for both the at() and the operator[]. However the OP reported that the problem only exists when he used at(). When he used operator[], it worked fine.
There is no need to speculate or guess indeed. The compiler already tells you what is wrong. What you need is not to make wild guesses, but try to understand what the compiler says.
Let's read again what the compielr says:
Box3D.cpp: In method `Box3D::Box3D(const Vec3DArray &)':
Box3D.cpp:53: no matching function for call to `vector<TVec3<double>,allocator<TVec3<double> > >::at (int &) const'
Box3D.cpp:55: no matching function for call to `vector<TVec3<double>,allocator<TVec3<double> > >::at (int &) const'
Can any one read it and understand it? Don't try to guess, just listen to the compiler. It's in plain English. The compiler is looking for a member function whose name is "at", for the instantiated vector class. But it can't find an "at" function with the correct parameter list that matches the code:
vertices.at(ii).x
How come? That's because the "at" function actually takes a parameter of the type size_type, which is actually an unsigned integer. But ii is a signed integer, so the compiler first looks for a version of the at that takes a signed integer as parameter. And could not find it.
Second, the compiler then speculate, maybe the ii in vertices.at(ii).x doesn't actually mean a "pass by value" parameter? Maybe it is a pass by reference parameter? So the ii could be a "int&" instead of an int. (The written form of both would be the same)
Then it look for a version of the at that takes an "int&" parameter. Needless to say, it can't find one. So at that point, it gives up and report the error. And since it give up not when looking for at(int), but when looking for at(int&), so it reports the error by telling us it could not find at(int&).
I think, by changing ii from an int to a size_type, or unsigned int, or by putting an explicit cast of ii to (size_type), the problem may be resolved.
Why wouldn't the compiler complain in the case of operator[]? That is because while regular named member functions like "at" could have many versions taking many different parameters. Operators are special and compiler KNOWS there is only one parameter the operator[] would take, i.e., size_type. So instead of looking for alternative versions that takes a signed integer, the compiler looks for ways to cast signed integer to size_type, and find that it can indeed do so without a problem.
Why would every thing work on VC++ compiler? Probably VC++ is more tolerate with minor syntax problems and so it is more diligent in trying all different things to make it workable. While as GCC is more strict in requiring the original code to be correct, so it makes less effort finding excuses for minor problems in the original source code.
Paul McKenzie
September 8th, 2002, 03:05 AM
Paul's speculation about constness being the cause of the problem is SURELY wrong, as any one using a bit of logic can seeI'll say this right now -- why do you respond with condescending terms such as "as any one using a bit of logic..."? This is why some here on CodeGuru have turned you off by putting your name in the "kill file". If anyone is more wrong on CodeGuru than right trying to pass themselves off as some sort of guru it is yourself. It seems that you want to make a living here reacting to other messages and adding your editorial, unneccessary comments instead of outright attempting to answer the OP's question. Graham's answer differs somewhat to willchop's. Do you see Graham insulting or belilittling willchop or vice-versa?
Maybe you're right, maybe you're wrong. Compilers are notorious for emitting messages that do not match what the actual problem is. I've never seen the at() function prototyped using a reference, which is the reason I answered the way I did. If it is at(size_type), and size_type is an unsigned, C++ rules would still make the OP's code valid since "int" will match a function that takes "unsigned".
void f(unsigned n)
{
}
int main()
{
int i = 0;
f(i);
}
There are no errors with the above code.
Regards,
Paul McKenzie
willchop
September 8th, 2002, 12:58 PM
Why wouldn't the compiler complain in the case of operator[]? That is because while regular named member functions like "at" could have many versions taking many different parameters. Operators are special and compiler KNOWS there is only one parameter the operator[] would take, i.e., size_type
I do not understand this statement. Overloaded operators are
not "special". In fact, you can overload the same operator
with as many parameters or types as you want - the same as
member function overloading. My implementation of vector has
the identical overloads for at() and operator[].
Any one using a bit of logic can see this. :)
regards, willchop
PaulWendt
September 8th, 2002, 04:33 PM
When I was using gcc-2.95.2, I noticed that vector::at and
string::at did not exist in their implementations. Mai was almost
correct, overlooking that int can be implicitly converted to an
unsigned int [as Paul McKenzie stated]. So ... what is your
solution?
You can only do one thing: upgrade to gcc-3.0 or greater.
They're currently at gcc-3.2 and it's not binary compatible with
any prior version so all shared libraries and applications will have
to be recompiled.
You could probably get by with just 2.95, though. 2.95 doesn't
include at() and I think some classes are missing altogether
[like ostringstream and istringstream] but here's a link to add
support for i/ostringstream to gcc-2.95:
http://gcc.gnu.org/faq.html#2.95sstream
--Paul
Paul McKenzie
September 9th, 2002, 04:38 AM
Originally posted by PaulWendt
When I was using gcc-2.95.2, I noticed that vector::at and
string::at did not exist in their implementations. Mai was almost
correct, overlooking that int can be implicitly converted to an
unsigned int [as Paul McKenzie stated]. So ... what is your
solution? Thanks Paul.
So the problem may be that at() does not exist. If this is the case, the error message was misleading. I conclude that there could be three scenarios for the error:
a) The at() function used by gcc is not const, and the vector passed in is const. I believe that the standard at() function that returns a const reference is declared as const.
b) The at() function has a non-standard prototype (a reference to an unsigned int). I have never seen at() declared using a reference parameter, and it wouldn't make sense anyway since you couldn't do, for example, at(3) (anyone using a bit of logic can see this ;)).
c) The at() function doesn't exist.
The problem of using an "int" instead of "unsigned" could only mean b), but you see how little sense it makes to declare it as a reference type. But since you stated that at() doesn't exist for this version of gcc, you can see where it gets you when you try to parse every sentence and word of an emitted compiler error message instead of looking at the code first and trying to get the context of what could have caused the error.
Regards,
Paul McKenzie
PaulWendt
September 9th, 2002, 06:21 AM
Originally posted by Paul McKenzie
So the problem may be that at() does not exist.
I confirmed it. I have installed 3.1.1 on our AIX box, but I left the
old headers for 2.95.2 there for weird occasions like this. I did
the following:
>grep "at(" *
I only received functions for their rope implementation.
(anyone using a bit of logic can see this ;)).
Boy ... consider yourself lucky. At least you didn't get told you'd
be a failure at any job interview; that's another of his favorites :)
--Paul
Andreas Masur
September 9th, 2002, 10:25 AM
Originally posted by PaulWendt
Boy ... consider yourself lucky. At least you didn't get told you'd
be a failure at any job interview; that's another of his favorites :)
Well...what do you expect from a guy who puts the following in his resume...
"I am well known due to my fantastic problem solving, bug-tracking and code optimization skills, and my expertise in digital audio signal processing and Windows multimedia programming. My colleagues call me “Master of Debugging”, “Master of Code Performance”."
Sorry but I could not resist... :D
AnthonyMai
September 9th, 2002, 10:44 AM
I confirmed it. I have installed 3.1.1 on our AIX box, but I left the
old headers for 2.95.2 there for weird occasions like this. I did
the following:
That's hardly a search. What if there is a space character between "at" and the "(", like "at ("?
I used GCC 2.95. There is nothing missing in the vector header file. If the problem is the const version of at is missing, the compiler should complain about a different error. It should match the existing "at" with how you code calls it, and realize that you need a none const reference to the vector class that calls the none-const at, and it will then complain it can't convert a const vector pointer (which is actually a reference) to a none-const vector pointer.
Here is an example:
void DoSomething(const intvec& myVector)
{
int j = 0;
myVector.at(j).fld1 = "Hello";
}
And the error while compiling:
Compiling...
test.cpp
c:\test\test\test.cpp(129) : error C2662: 'at' : cannot convert 'this' pointer from 'const class std::vector<class SomeClass,class std::allocator<class SomeClass> >' to 'class std::vector<class SomeClass,class std::allocator<class SomeClass> > &'
Conversion loses qualifiers
c:\test\test\test.cpp(129) : error C2228: left of '.fld1' must have class/struct/union type
Error executing cl.exe.
Paul McKenzie
September 9th, 2002, 10:56 AM
Originally posted by AnthonyMai
That's hardly a search. What if there is a space character between "at" and the "(", like "at ("?
I used GCC 2.95. There is nothing missing in the vector header file.Then post the line in the header that declares the at() function. Do you think we're going to take your word for it? The at() function is missing from the SGI STL documentation and most likely, their implementation. I wouldn't be surprised if gcc doesn't have it either.
Compiling...
test.cpp
c:\test\test\test.cpp(129) : error C2662: 'at' : cannot convert 'this' pointer from 'const class std::vector<class SomeClass,class std::allocator<class SomeClass> >' to 'class std::vector<class SomeClass,class std::allocator<class SomeClass> > &'
Conversion loses qualifiers
c:\test\test\test.cpp(129) : error C2228: left of '.fld1' must have class/struct/union type
Error executing cl.exe.
Using VC++ to confirm something that gcc reports to be an error?
Regards,
Paul McKenzie
AnthonyMai
September 9th, 2002, 11:05 AM
Well...what do you expect from a guy who puts the following in his resume...
The above post pertains nothing to the topic of programming
and seriously violated my privacy, and as well as violated my copyright, by posting my resume, without my written consensus. Hence it breaks the rule of this board.
This behavior is totally unacceptable. If the moderator continue
to allow people to reveal other user's privacies on this board unchecked, not only this board can not survive for long, it could also break the US laws.
I am hereby requesting that the moderator of this board ban
Andreas Masur from accessing this board. I also reserve the right to pursue this issue through the legal channel should Mr. Andreas Masur's violation of my privacy continues.
Finally, Mr. Andreas Masur should be able to contact my former employer and find out that I am indeed adequately describing myself in my resume. BTW, both me and boss are pretty happy with what I am doing on my current job and probably won't need to write another resume for a while.
PaulWendt
September 9th, 2002, 11:16 AM
AnthonyMai said:
That's hardly a search. What if there is a space character between "at" and the "(", like "at ("?
I used GCC 2.95. There is nothing missing in the vector header file....
You make a valid point in that I maybe used an inadequate
search, but GNU uses a bunch of formatting conventions. That's
not to say that conventions haven't been broken before, but
it's their style to put an opening parenthesis right after the
function name.
As far as saying "there is nothing missing in the vector header",
that's just not correct for MY installation of gcc. I had version
2.95.2; I don't know what they put into 2.95.3 and I don't know
what they put into 2.96. You could use vector<>::at with all the
const, non-const, int, unsigned int etc. overloads until you were
blue in the face, the vector<>::at simply didn't exist with 2.95.2
on any of our unix systems.
No, it's not just me, either. I did a search on google and other
people were complaining about vector not having at with gnu
2.95 [not sure about the smaller version number]. string didn't
have at, either. gcc-3.0 was eagerly anticipated by a lot of the
open source development community because of its closer
adherence to the recently approved ISO standard for C++. It's
because of vector<>::at and the i/ostringstream stuff I mentioned
earlier.
--Paul
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.