Разрешить постоянные и неконстантные указатели на функции-члены - PullRequest
4 голосов
/ 10 октября 2019

В приведенном ниже фрагменте кода я хочу иметь возможность звонить A::foo из doWork.

Однако, поскольку есть две перегрузки foo (const и не const)), компилятор не может определить, что я имею в виду при вызове doWork. Есть ли способ сказать компилятору, что я имел в виду, какой.

Я не могу изменить struct A.

Могу ли я сделать что-нибудь в подписи doWork или в вызове doWork, чтобы всегда выбирать, скажем, константное.

Одно из известных мне решенийдать тип указателя на функцию в качестве аргумента doWork вместо шаблона (как это) void doWork(void (A::*fun)(void) const){ Но это немного уродливо, и я хочу найти решение на основе шаблона (если оно существует)

struct A{
    void foo() const {
    }
    void foo(){
    }
    void bar(){
    }
    void bar() const {
    }
};

template<typename F>
void doWork(F fun){
    const A a;
    (a.*fun)();
}

int main()
{
    doWork(&A::foo); //error: no matching function for call to ‘doWork()’
    doWork(&A::bar); // error: no matching function for call to ‘doWork()’
    return 0;
}

Ответы [ 2 ]

3 голосов
/ 10 октября 2019

Вы можете использовать static_cast, чтобы указать, какой из них следует использовать.

static_cast также можно использовать для устранения неоднозначности перегрузок функций путем выполнения функции дляпреобразование указателя в определенный тип, как в

std::for_each(files.begin(), files.end(),
              static_cast<std::ostream&(*)(std::ostream&)>(std::flush));

например,

doWork(static_cast<void (A::*)(void) const>(&A::foo));
doWork(static_cast<void (A::*)(void) const>(&A::bar));

Или указать аргумент шаблона явно.

doWork<void (A::*)(void) const>(&A::foo);
doWork<void (A::*)(void) const>(&A::bar);
1 голос
/ 10 октября 2019

Вы можете использовать:

template <typename T>
void doWork(void (T::*fun)() const){
    const A a;
    (a.*fun)();
}

В более шаблонном шаблоне функции будет использоваться const T a.

template <typename T>
void doWork(void (T::*fun)() const){
    const T a;
    (a.*fun)();
}

Обратите внимание, что вторая версия нигде не принимает A.

...