3
#include <iostream>

template <typename Type, typename ReturnType>
struct mem_fun_ptr_t
{
    typedef ReturnType (Type::*Func)();
    Func func;
public:
    mem_fun_ptr_t(Func f):
        func(f) {}
    ReturnType operator () (Type *p) { return (p->*func)(); }
};

// non-const version
template <typename T, typename R>
mem_fun_ptr_t<T, R> mem_fun_ptr(R (T::*Func)())
{
    return mem_fun_ptr_t<T, R>(Func);
}

// const version
template <typename T, typename R>
mem_fun_ptr_t<T, R> mem_fun_ptr(R (T::*Func)() const)
{
    typedef R (T::*f)();
    f x = const_cast<f>(Func); //error
    return mem_fun_ptr_t<T, R>(x);

    //but this works:
    /*
    f x = reinterpret_cast<f>(Func);
    return mem_fun_ptr_t<T, R>(x);
    */
}

int main()
{
    std::string str = "Hello";
    auto x = mem_fun_ptr(&std::string::length);
    std::cout << x(&str);
    return 0;
}

I think you've already guessed what I'm writing. Yes, I should implement mem_fun_ptr_t<> with Func const func; attribute. And it will be the right solution. But I'm studing and I want to know all. So how to const_cast member function pointer? I've tried f x = const_cast<f*>(Func) but I get errors.

Thanks for your feedbacks

yivo
  • 3,324
  • 1
  • 18
  • 23

2 Answers2

3

You can't const_cast a pointer to member this way. And reinterpret_cast technically exhibits undefined behavior. It is precisely for this reason that the standard library contains separate mem_fun_t and const_mem_fun_t classes, with mem_fun overloads manufacturing one or the other.

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
3

Pass in the type of the member function pointer to your template as well: (Live at ideone.com):

template <typename Type, typename ReturnType, typename MemFuncType>
struct mem_fun_ptr_t
{
    MemFuncType func;
public:
    mem_fun_ptr_t(MemFuncType f) :
      func(f) {}
    ReturnType operator () (Type *p) const { return (p->*func)(); }
};

// non-const version
template <typename T, typename R>
mem_fun_ptr_t<T, R, R (T::*)()>
mem_fun_ptr(R (T::*Func)())
{
    return mem_fun_ptr_t<T, R, R (T::*)()>(Func);
}

// const version
template <typename T, typename R>
mem_fun_ptr_t<const T, R, R (T::*)() const>
mem_fun_ptr(R (T::*Func)() const)
{
    return mem_fun_ptr_t<const T, R, R (T::*)() const>(Func);
}
Casey
  • 41,449
  • 7
  • 95
  • 125
  • @Casey I don't believe this is valid code. While GCC accepts it, MSVC2012 and Clang 3.0 report errors. – Igor Tandetnik Jul 13 '13 at 14:19
  • @Casey Here's a simple example, not involving templates, of what your approach appears to be doing: http://ideone.com/VP1my6 . It fails to compile, on GCC too. When you define `R (T::pm)()`, even if `T` is a `const C` for some class `C`, doesn't mean that such a pointer can point to a const member `C::f() const`. That your template example is accepted looks like a compiler bug to me. – Igor Tandetnik Jul 13 '13 at 14:29
  • @IgorTandetnik That's what I get for drinking while cruising SO. Replace with sober answer that is actually standard conforming. – Casey Jul 13 '13 at 21:27