lucas clemente
lucas clemente

Reputation: 6389

Cast const member function to non-const

Is casting the constness of member function pointers defined in C++? Is the following valid code?

struct T {
  void foo(int i) const { std::cout << i << std::endl;};
};

void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int)       = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1);

Update:

The reason why I need this is that I'm writing a function that accepts both an object and a member function pointer to that object. I need a version for const objects (accepting only const functions) and a normal one. Since I don't want duplicate code, my idea was to put the actual code in the non-const version and call it from the const one, casting away any consts.

Upvotes: 5

Views: 3963

Answers (5)

Gerry Candy
Gerry Candy

Reputation: 36

The only was to resolve the ambiguity is to perform a static_cast, this is basically a language feature

#include <boost/typeof/typeof.hpp>
struct Test
{
    const int& foo();
    const int& foo() const;
};

int main()
{
    typedef const int&(Test::*non_const_ptr)();
    typedef const int&(Test::*const_ptr)()const;
    BOOST_TYPEOF(static_cast<non_const_ptr>(&Test::foo)) ss;
}

Upvotes: 0

klm123
klm123

Reputation: 12865

Compiler eats it. But the backward cast is more useful.

And again but - it is better to don't use it, const_cast is usually just a quick and dirty solution, which you apply only when there are not any other solution.

Answer to update

If I understand you correctly you are going to use one object and two function. First function accepts const object and const member-function, second - non-const object and non-const member-function.

According to given information you can change second function to accept non-const object and const member-function. And give them one non-const object and its const member-function.

Upvotes: 3

Evan Dark
Evan Dark

Reputation: 1341

You can do it, but it has no meaning, wherever you can call f2, you can also call f1 too. You should cast in the other way. But if something, you should cast the object, not the function.

void (T::*f1)(int) const = &T::foo;
void (T::*f2)(int)       = reinterpret_cast<void (T::*)(int)>(f1);
T t;
(t.*f2)(1); // compiles
(t.*f1)(1); // this compiles too!!

but if you have

const T t;
(t.*f2)(1); // error t is const
(t.*f1)(1); // still compiles

Upvotes: 0

Alexander Putilin
Alexander Putilin

Reputation: 2342

I don't see a reason for doing this: even if you could, you'd make it more restrictive. Let's say you have a class Foo:

class Foo {
  void f() const;
  void g();
}

And some snippet of code:

Foo a;
const Foo b;

Then you can call both a.f() and a.g(), but not b.g() because b is const. As you can see, placing const after a member function makes it less restrictive, not more.

And, by reinterpret_casting this pointer, you'll get the pointer with exact same value(due to the nature of reinterpret_cast), and if you try to call it, you'll get into the same T::foo()

Upvotes: -1

user529758
user529758

Reputation:

Yes, it is defined, but you maybe don't want it if the function is really const, because some compiler optimizations (namely return value caching) depend on the function being const.

Upvotes: 1

Related Questions