Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to expose a map of pointers as a map of const pointers?

I have a class with an std::map of pointers as a member. Now, I'd like to expose that member in a read only fashion: modification is not allowed for neither the map, nor the objects pointed to. Internally I need those pointers to be non-const, and I want to expose them as const.

I do have a solution that compiles at least, but I'd like to know if there's any hidden problems I'll run into with this.

class A
{
public:
  const std::map<int, const float*>& GetMap() const { return *(reinterpret_cast< const std::map<int, const float*>* >( &m_Map)); }

private:
  std::map<int, float*> m_Map;
};

There's a possible problem I can think of: if the internal layout of std::map is different for maps of pointers and maps of const pointers, then this will cause ugly bugs. But I cannot think of any sane reason why that would be the case. Anybody has any idea?

To clarify: I am aware that this is a hack, and there are safer solutions (like separate accessor functions). I am just wondering if this would break right away because of some piece of information I'm missing.

like image 524
Zed Avatar asked Jun 30 '11 17:06

Zed


People also ask

What is a constant pointer?

To understand a constant pointer, let us recall definition of a constant variable. Constant variable is a variable whose value cannot be altered throughout the program. Similarly, constant pointer is a pointer variable whose value cannot be altered throughout the program.

How to re-assign a constant pointer to a single object?

The statement *const_ptr = 10; assigns 10 to num1. Next we tried re-assignment of constant pointer i.e. const_ptr = &num2;. The statement will generate compilation error, since a constant pointer can only point to single object throughout the program. The last two printf () statements are used to test value of num1.

What are pointers in C programming?

Pointers are the most powerful as well as complex component of C programming. For newbies, it’s like learning rocket science in C. However, I have tried my best to simplify things. In this ongoing series of C programming tutorial, I have explained many concepts related to pointers.

When to initialize a constant pointer in C++?

Note: You must initialize a constant pointer at the time of its declaration. Note: We use const keyword to declare a constant pointer. The compiler will generate compilation error on failure of any of the two conditions. You must initialize a constant pointer during its declaration. A constant pointer must not be re-assigned.


2 Answers

This is of course undefined (EDIT: it looks like it's actually only unspecified) behavior because the two maps are (from the language point of view) totally unrelated types. It may appear to work now but sometime it's going to break and cause a ton of headaches.

Did you consider that instead of exposing an implementation detail (that you're using map internally) you could provide const_iterators and a find method for your class's public interface instead?

EDIT: See 5.2.10/7:

A pointer to an object can be explicitly converted to a pointer to an object of different type. 65) Except that converting an rvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.

From that quote we conclude that casting from the map with non-const value type to the map with const value type has unspecified behavior. Further, actually dereferencing the converted pointer would probably violate the strict aliasing rules and result in undefined behavior.

like image 101
Mark B Avatar answered Sep 25 '22 00:09

Mark B


You could hold it as a map<int, const float *> and const_cast internally when you need to. This is ugly but legal (as long as you know that all the values pointed to really aren't const).

At least it doesn't involve Undefined Behaviour which I'm pretty certain your solution does. Although as you say it will probably work most of the time on most platforms.

like image 41
Alan Stokes Avatar answered Sep 23 '22 00:09

Alan Stokes