How to Reliably Get an Object's Address When Operator& Is Overloaded

How can I reliably get an object's address when operator& is overloaded?

Update: in C++11, one may use std::addressof instead of boost::addressof.


Let us first copy the code from Boost, minus the compiler work around bits:

template<class T>
struct addr_impl_ref
{
T & v_;

inline addr_impl_ref( T & v ): v_( v ) {}
inline operator T& () const { return v_; }

private:
addr_impl_ref & operator=(const addr_impl_ref &);
};

template<class T>
struct addressof_impl
{
static inline T * f( T & v, long ) {
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}

static inline T * f( T * v, int ) { return v; }
};

template<class T>
T * addressof( T & v ) {
return addressof_impl<T>::f( addr_impl_ref<T>( v ), 0 );
}

What happens if we pass a reference to function ?

Note: addressof cannot be used with a pointer to function

In C++ if void func(); is declared, then func is a reference to a function taking no argument and returning no result. This reference to a function can be trivially converted into a pointer to function -- from @Konstantin: According to 13.3.3.2 both T & and T * are indistinguishable for functions. The 1st one is an Identity conversion and the 2nd one is Function-to-Pointer conversion both having "Exact Match" rank (13.3.3.1.1 table 9).

The reference to function pass through addr_impl_ref, there is an ambiguity in the overload resolution for the choice of f, which is solved thanks to the dummy argument 0, which is an int first and could be promoted to a long (Integral Conversion).

Thus we simply returns the pointer.

What happens if we pass a type with a conversion operator ?

If the conversion operator yields a T* then we have an ambiguity: for f(T&,long) an Integral Promotion is required for the second argument while for f(T*,int) the conversion operator is called on the first (thanks to @litb)

That's when addr_impl_ref kicks in. The C++ Standard mandates that a conversion sequence may contain at most one user-defined conversion. By wrapping the type in addr_impl_ref and forcing the use of a conversion sequence already, we "disable" any conversion operator that the type comes with.

Thus the f(T&,long) overload is selected (and the Integral Promotion performed).

What happens for any other type ?

Thus the f(T&,long) overload is selected, because there the type does not match the T* parameter.

Note: from the remarks in the file regarding Borland compatibility, arrays do not decay to pointers, but are passed by reference.

What happens in this overload ?

We want to avoid applying operator& to the type, as it may have been overloaded.

The Standard guarantees that reinterpret_cast may be used for this work (see @Matteo Italia's answer: 5.2.10/10).

Boost adds some niceties with const and volatile qualifiers to avoid compiler warnings (and properly use a const_cast to remove them).

  • Cast T& to char const volatile&
  • Strip the const and volatile
  • Apply the & operator to take the address
  • Cast back to a T*

The const/volatile juggling is a bit of black magic, but it does simplify the work (rather than providing 4 overloads). Note that since T is unqualified, if we pass a ghost const&, then T* is ghost const*, thus the qualifiers have not really been lost.

EDIT: the pointer overload is used for pointer to functions, I amended the above explanation somewhat. I still do not understand why it is necessary though.

The following ideone output sums this up, somewhat.

Why would anyone want to overload the & (address-of) operator?

If you're dealing with any sort of wrapper objects, you might want or need to transparently forward the access to the wrapper to the contained object. In that case, you can't return a pointer to the wrapper, but need to overload the address-of operator to return a pointer to the contained object.

If an operator is overloaded for a C++ class how could I use a default operator instead?

I've seen this case pop up in an ISO meeting as it broke some offsetof() macro implementations (LWG 273). The solution: &reinterpret_cast<unsigned char&>(variable)

Most portable and reliable way to get the address of variable in C++

It is standard-complaint. The issue was brought to the attention of the ISO C++ committee in relation to problems with offsetof implementations that broke on this. Amongst the solutions considered were tightening the POD definition, or adding an extra restriction on types to be used with offsetof. Those solutions were rejected when the reinterpret_cast solution was brought up. Since this offered a standard-compliant way around the problem, the committee did not see a need to add extra requirements to the offsetof, and left fixes to the implementations.

How to reliably calculate the memory address of an object

If the class hierarchy is polymorphic, you can use dynamic_cast<void*>(this) to obtain the address of the most derived object of which *this is a subobject.

See also this question.


If your class hierarchy is not polymorphic, you cannot know dynamically whether a given base object is most-derived, and if it is not, you cannot know what its most-derived object is. However, in that case you also cannot destroy the object since you don't have access to the most-derived destructor, and so you will generally not have need to releasing the memory. It is true, however, that ou cannot look up an object's allocation trace if you cannot determine its most-derived object.

Getting memory address in c++ without ampersand (&) operator

There is std::addressof for exactly this purpose

C++ operator print object address

I think I'd do the job just slightly differently than I've seen in the answers so far -- I'd explicitly cast the address to void * before printing:

std::ostream &operator<<(std::ostream &os, MyCls const &object) { 
return os << "(" << static_cast<void const *>(&object) << ") MyClass\n";
}

I generally don't like casts, but in this case I think it's worthwhile to make it clear that your intent is to print out the address, so somebody doesn't mistake it for a bug/accident.

C++: how to return object's set state when used as logical value

You can define a bool operator, as follows

#include <iostream>

struct Object{
bool state;
explicit operator bool()const{
return state;
}
};
int main(){

Object o1;
Object o2;
o1.state = false;
o2.state = true;
std::cout << "\no1 state is " << (o1? "true": "false");
std::cout << "\no2 state is " << (!o2? "false": "true");
}

The output is

o1 state is false
o2 state is true

Live

Why is overloading operator&() prohibited for classes stored in STL containers?

Without having looked at the links, I suppose the tricks in boost::addressof() were invented well after the requirement to not to overload unary prefix & for objects to be held in containers of the std lib.

I vaguely remember Pete Becker (then working for Dinkumware on their standard library implementation) once stating that everyone who overloads the address-of operator and expects their standard library implementation still to work should be punished by having to implement a standard library which does this.

Can we add two objects by overloading - operator

Yes, any behavior can be given to the operators.

The recommendation is, however, to avoid overloading operators unless they have the usual meaning.

Sometimes libraries use operators to create small Domain Specific Languages (DSLs), but one must balance brevity and readability.



Related Topics



Leave a reply



Submit