Skip to main content
gamedev.net
🔒 Locked

Operator overloading operator& and std.

Started by __fold Jul 4, 2004 at 4:25 AM 14 replies 2.4k views
Original Post
__fold
__fold
I have a template called A that has constructor, destructor and a function that overloads operator&. When I try to put objects of type A into a std::vector it fails. Here's an example. It works just fine in VC++ 6.0 sp 6 but it doesn't work in GCC 3.2.

#include <vector>
#include "A.h"

int main(void)
{
  std::vector< NS::A<float> > vec;
  NS::A<float> a;
  vec.push_back(a);

  return 0;
}
Deos std use my overloaded opertator& when it tries to get the address of the object?
__fold
__fold
I can't edit for some reason...
...and I wonder where the brackets around 0 came from. :)
Jingo
Jingo
Whats the error message? And show the definition of A.
__fold
__fold
Ok, here's an complete example. Should have posted it from the beginning...

class A

namespace B {	template <typename T> class A {	private:		T x[3];	public:		A(T y) {};		virtual ~A() {};		inline T* operator&() { return x; }	};}


main func

#include <vector>#include "A.h"int main(void){	B::A<int> a([2]);	std::vector< B::A<int> > vec;	vec.push_back(a);	return [0];}


Error message from GCC (the last lines are the most import I guess):
C:/program/programmering/Dev-Cpp/include/c++/bits/stl_construct.h: In function
void std::_Construct(_T1*, const _T2&) [with _T1 = int, _T2 = B::A]':
C:/program/programmering/Dev-Cpp/include/c++/bits/stl_uninitialized.h:87: instantiated from
_ForwardIter std::__uninitialized_copy_aux(_InputIter, _InputIter, _ForwardIter, __false_type) [with _InputIter = __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, _ForwardIter = __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >]'
C:/program/programmering/Dev-Cpp/include/c++/bits/stl_uninitialized.h:112: instantiated from _ForwardIter std::uninitialized_copy(_InputIter, _InputIter, _ForwardIter) [with _InputIter = __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >, _ForwardIter = __gnu_cxx::__normal_iterator*, std::vector, std::allocator > > >]'
C:/program/programmering/Dev-Cpp/include/c++/bits/stl_vector.h:901: instantiated from
void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<_Tp*, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = B::A, _Alloc = std::allocator >]'
C:/program/programmering/Dev-Cpp/include/c++/bits/stl_vector.h:496: instantiated from void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = B::A, _Alloc = std::allocator >]'
main.cpp:8: instantiated from here
C:/program/programmering/Dev-Cpp/include/c++/bits/stl_construct.h:78: cannot
convert
const B::A' to `int' in initialization

where main line 8 is vec.push_back(a);
SiCrane
SiCrane
Overloading the address of operator on a class makes it ineligible for use in a standard library container (unless you define it to do the exact same thing as the built in address of operator). Specifically, it violates the requirements set down in section 20.1.3 of the C++ standard.
snk_kid
snk_kid
To add to that what it looks like what your trying achieve can be done with an overloaded cast operator e.g.

operator const T*() const {   return x;}operator T*() {   return x;}
__fold
__fold
SiCrane: ok, but I can't see that I'm doing it in this code. The pointer to data and the pointer to the object are both const and it should be the same address.

(I just saw that I had a virtual method in my template, which I thought was invalid.)
Jingo
Jingo
The pointers may or may not be the same, but the standard requires the type of the pointer returned by your operator& to be A* or const A*, and it is returning int*, which is what the compiler error is telling you.
__fold
__fold
Jingo and you other guys are probably right. But it works fine in VC++ 6 and I got the idea of solving a problem this way from the 3ds-max SDK where they have a vector class that looks something like this.

class Vector {private:  float x,y,z;public:  Vector() {}  ~Vector() {}  const float* operator&() { return &x }}
__fold
__fold
Sure the pointers are the same, at least for basic types. Otherwise it wouldn't be possible wo have an array of vertex-objects without losing alot of speed.

If you have an array of vertex objects and iterate through them. You will loose more than 25 percent of execution time if you add extra data between the objects. If you have an object with float x,y,z then the array will become x,y,z,x,y,z,x,y,z and so on. The adress of x will always be the same as the address of the object. If you have a vertex class, just add a float w and see how the speed decreases alot. At least on Athlon XP+ CPUs.
Jingo
Jingo
Well the class is fine unless you want to instantiate the standard containers with it. If you want to use it in the standard containers then you must meet the requirements stated in this thread.

And the pointers in the original A class are not the same in VC++ 2003.NET.
snk_kid
snk_kid
Quote:
Original post by __fold
Jingo and you other guys are probably right. But it works fine in VC++ 6 and I got the idea of solving a problem this way from the 3ds-max SDK where they have a vector class that looks something like this.

*** Source Snippet Removed ***


If your doing this so you can pass a vector to a some function that requires an array or a pointer to an array (as in opengl functions) as it's argumenets e.g.

Vector3f v;glVertex3fv(v);


Then you overload the cast operators for that e.g.

Vector3
#include <cstddef>template< typename T >class Vector3 {public:   typedef size_t             size_type;   typedef ptrdiff_t          difference_type;   typedef T                  value_type;   typedef T*                 pointer;   typedef const value_type*  const_pointer;   typedef value_type&        reference;   typedef const value_type&  const_reference;   typedef Vector3<T>         _self;private:   value_type _n[3];public:     operator const T*() const {           return _n;   }   operator T*() {           return _n;   }   //default constructor   Vector3(T x = 0, T y = 0, T z = 0);   Vector3(T n[]);   //copy constructor   Vector3(const _self& _v);   //assigment   _self& operator=(const _self& _v);   const_reference operator[](difference_type i) const {        return _n;   }   reference operator[](difference_type i) {       return _n;   }    // add more methods};


EDIT: Provide constant & non-constant version of the function

[Edited by - snk_kid on July 4, 2004 6:40:58 AM]
Jingo
Jingo
You shouldn't really use names beginning with an underscore snk_kid, they are reserved by the standard to the implementation for use in the global namespace. For all you know _n could be a macro for int.
__fold
__fold
snk_kid: Hmm, that is what I want to do when I think about it. I really have to check why I have overloaded operator& from the bginning. Now atleast I know why it doesn't work and I agree that it shouldn't work. It's a cast I probably thought of when I designed the class.

Thanks for all the replies!
Fruny
Fruny
Quote:
Original post by Jingo
You shouldn't really use names beginning with an underscore snk_kid, they are reserved by the standard to the implementation for use in the global namespace. For all you know _n could be a macro for int.


Well, he's not at global scope, he's in a class scope. That makes names beginning with a single underscore and a lowercase letter perfectly legitimate. Considering that macros do not respect scope, _n could not be a macro for int.

It is names starting with two underscores or an underscore and an uppercase letter which are reserved at any scope, for any usage. So __n or _N could be a macro, or a special compiler keyword (__declspec anyone?)
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Jingo
Jingo
Ok i see.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.