elmo
elmo

Reputation: 1256

Template argument deduction from pointer to member function with const and non-const versions

I have a code like this:

#include <iostream>

template <typename T, typename FT>
void test( const FT & (T::*ptr)() const )
{
    std::cout << "const exists" << std::endl;
}

template <typename T, typename FT>
void test( FT & (T::*ptr)() )
{
    std::cout << "non-const exists" << std::endl;
}


struct A {
    const double & a() const { return a_; }
    double & a() { return a_; }

    private:
        double a_;
};

struct B {
    const double & b() const { return b_; }

    private:
        double b_;
};



int main( int argc, char **argv )
{
    test(&A::a);
    test(&B::b);

    return 0;
}

Which does not compile with error message:

prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:35: error: call of overloaded ‘test(<unresolved overloaded function type>)’ is ambiguous
prog.cpp:4: note: candidates are: void test(const FT& (T::*)()const) [with T = A, FT = double]
prog.cpp:10: note:                 void test(FT& (T::*)()) [with T = A, FT = double]

It is quite clear why compiler doesn't know what to do. My question is how to call the one with non-const exists if there is non-const version and const exists if there is only const version?

Note: for this question I assume that non-const version cannot exist without const version. However if you have a solution for more general case when you can differentiate also the case when the non-const exists but const does not it would be also appreciated.

Upvotes: 1

Views: 410

Answers (1)

elmo
elmo

Reputation: 1256

So simple solution (ideone):

#include <iostream>

struct Tester {
    template <typename T, typename FT>
    void operator()( const FT & (T::*ptr)() const ) const
    {
        std::cout << "const exists" << std::endl;
    }

    template <typename T, typename FT>
    void operator()( FT & (T::*ptr)() )
    {
        std::cout << "non-const exists" << std::endl;
    }
};


struct A {
    const double & a() const { return a_; }
    double & a() { return a_; }

    private:
        double a_;
};

struct B {
    const double & b() const { return b_; }

    private:
        double b_;
};



int main( int argc, char **argv )
{
    Tester t;
    t(&A::a);
    t(&B::b);

    return 0;
}

Upvotes: 1

Related Questions