Search code examples
c++language-lawyertemplate-meta-programming

Generic way of getting pointer to member const overload without explicit cast


I have seen the following topic: Resolve const and non-const member function pointer

But I wonder if there's a generic-programming friendly way of doing it as of C++11 or newer. For the sake of example, imagine the following class:

struct S
{
    int v = 42;
    int& value() { return v;}
    int value() const {return v;}
};

the following helper class

template<typename T>
struct Holder
{
    using TYPE = T;
};

However when I try this:

    auto l = [](auto holder) 
        -> decltype(&(std::add_const_t<typename decltype(holder)::TYPE>::value))
        {
            return &(std::add_const_t<typename decltype(holder)::TYPE>::value);
        };

I keep getting the following error from GCC: error: 'decltype' cannot resolve address of overloaded function while clang just crashes during compilation.

Why is that, if:

  static_assert(
    std::is_same_v<
        const S, 
        std::add_const_t<Holder<std::decay_t<S>>::TYPE>>, 
    "");

https://godbolt.org/z/e5E7Ts156

Should that be the case, or have I bumped into a weird defect/corner case?


Solution

  • You can do something like this:

    template <typename Owner, typename Ret, typename... Arg>
    constexpr auto getConstFuncPtr(Ret (Owner::*mfpc)(Arg...) const) { return mfpc; }
    
    template <typename Owner, typename Ret, typename... Arg>
    constexpr auto getNonConstFuncPtr(Ret (Owner::*mfpnc)(Arg...)) { return mfpnc; }
    
    auto mfpc  = getConstFuncPtr(&S::value);
    auto mfpnc = getNonConstFuncPtr(&S::value);
    

    There is an implicit conversion (which is not a cast) that helps decide which function to take.