views:

89

answers:

2

In C++, the compiling the following code:

std::pair <int, int>  x;
static_cast <std::pair <const int, int>*> (&x);

gives an error:

error: invalid static_cast from type ‘std::pair<int, int>*’ to type ‘std::pair<const int, int>*’

I more or less understand why it happens, as cv-qualifying a type in a template parameter list can, in principle, give an "incompatible" result. And even if in this case it doesn't, compiler has no way to know it.

Anyway, is there a non-hackish way to perform this conversion? I'm wary of using reinterpret_cast for anything as I've been by type-punning problems before. Also, I can't use temporaries since this is in performance-critical code.

EDIT:

Here is what I'm doing. I'm implementing a custom container interface-compatible with std::unordered_map. Because of that, its value_type needs to be a pair <const key_type, mapped_type>. For some optimization, I need to internally store the values as pair <key_type, mapped_type>, without const. However, if I do that, I can't (without reinterpret_cast) implement iterators over the container, as they need to return references to values and I have only references to these non-const pairs.

+1  A: 
Kirill V. Lyadvinsky
A: 

How about this:

template< typename T1, typename T2 >
struct ref_pair {
public:
    typedef const T1 first_type;
    typedef T2 second_type;

    ref_pair(first_type& f, second_type& s) : f_(f), s_(s) {}

    first_type& first() {return *f_;}
    second_type& second() {return *s_;}
private:
    first_type* f_;
    second_type* s_;
};

I know, it's different, those are functions. If you're really desperate, you can turn first and second into objects of some proxy type which delay-evaluate *f_ and *s_.
However, in the end there's always a way users can tell the difference.


I think the following would be reasonably safe and portable, although, of course, with reinterpret_cast nothing is guaranteed:

std:::pair<const int,int>& rx = reinterpret_cast<std:::pair<const int,int>&>(x);

It feels dirty, though. I'm now going to wash my hands.

sbi