Question

...even though pointers to member functions are strange animals?

I am coding a library to bind C++ classes to Lua. I have to deal with the type erasure caused by pushing certain types object onto the Lua stack (and so casting them to void*). For this reason, but also to avoid excessive proliferation of different templates for different kinds of data (non const and const object, non const and const members, and in the future double everything for volatile and non volatile....), I manage constness of the object bound to Lua at runtime by simply setting a certain flag.

Now, I'm dealing with pointers to member function. Following my design so far, I'd be glad if I could safely cast a pointer to const member function to a non-const one, then reuse the same template for non-const, and deal with constness at runtime with the aforementioned flag.

But there's another hint that makes me wonder if this is really possible. Consider the code below:

#include <iostream>
#include <typeinfo>
using namespace std;

struct A{
    const int a;
    int b;
};

template<typename T> struct tmpl;

template<typename Class, typename FT> struct tmpl<FT(Class::*)>{
    static void f(){
        cout<<"non const"<<endl;
    }
};

//Try commenting this out, code compiles, both A::a and A::b instantiate the first template
template<typename Class, typename FT> struct tmpl<const FT(Class::*)>{
    static void f(){
        cout<<"const"<<endl;
    }
};

int main(){
    cout<<typeid(&A::a).name()<<endl;   //prints "M1AKi"
    tmpl<decltype(&A::a)>::f();         //prints "const"
    cout<<typeid(&A::b).name()<<endl;   //prints "M1Ai"
    tmpl<decltype(&A::b)>::f();         //prints "non const"
    //Let's do what it seems that can be done implicitly (providing only one template specialization) in an explicit way
    int(A::*memb)=(int(A::*))&A::a;
    cout<<typeid(memb).name()<<endl;    //prints "M1Ai"
    tmpl<decltype(memb)>::f();          //prints "non const"
}

It seems so that regardless these animals can even change their own size, in certain circumstances you can safely cast (or at least, const_cast) them to other types (if they make sense).

So, is my reasoning horribly wrong in one of the steps, or can I do this, regardless of the compiler? Can I play the same way with pointers to const member functions?

Was it helpful?

Solution

In the "non-const" specialization, FT is simply deduced to include the const qualifier. It doesn't disappear, it's just passed in.

Try this:

template<typename Class, typename FT> struct tmpl<FT(Class::*)>{
    static void f(){
        if ( std::is_const< FT >::value ) {
            cout<<"const as non const"<<endl;
        } else {
            cout<<"non const"<<endl;
        }
    }
};

http://ideone.com/g2Eie

If you want to kill a const, then const_cast is the only viable tool for the job.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top