Подтвердить что ты не робот

Почему аргумент шаблона не может быть выведен в этом контексте?

Может ли кто-нибудь объяснить, почему компиляторы (g++, visual С++) не могут вывести аргумент шаблона в этом случае?

struct MyClass
{
    void Foo(int x)&  {}
    void Foo(int x)&& {}
};

template<typename T>
void CallFoo(void(T::*func)(int)&)
{
    //create instance and call func
}

int main()
{
   CallFoo(&MyClass::Foo); // Fails to deduce T
}

Почему компиляторы не могут вывести T в MyClass? Это происходит только для методов, перегруженных квалификаторами ref. Если метод перегружен конструкциями или типами параметров, все работает нормально. Кажется, что только Clang может вывести T в этом случае.

4b9b3361

Ответ 1

Подводя итог обсуждению в комментариях: поддержка ссылочных функций-членов в качестве аргументов шаблона является относительно новой функцией для некоторых компиляторов. Тем не менее, последние версии большинства компиляторов будут компилировать такой код.


Например:

#include <iostream>

struct MyClass
{
    void Foo(int) const &
    {
        std::cout << "calling: void Foo(int) const &\n";
    }
    void Foo(int) const &&
    {
        std::cout << "calling: void Foo(int) const &&\n";
    }
};

template<typename T>
void CallFoo_lvalue(void (T::*foo)(int) const &)
{
    T temp;
    (temp.*foo)(0);
}

template<typename T>
void CallFoo_rvalue(void (T::*foo)(int) const &&)
{
    (T{}.*foo)(0);
}

int main()
{
   CallFoo_lvalue(&MyClass::Foo);
   CallFoo_rvalue(&MyClass::Foo);
}

Будет компилироваться с помощью:

  • gcc (работает с 7.0.0)
  • Visual С++ (работает с v19.10.24903.0)

производя следующий вывод:

calling: void Foo(int) const &
calling: void Foo(int) const &&

Для тех, кто блуждает, что & и && для: здесь цитата из @JustinTime:

В принципе, и является рефлексиатором lvalue, и && является rvalue ref-qualifier (привязывается к временному объекту); в его примере MyClass m; m.Foo(3); назвал бы верхний, а MyClass {}. Foo (3); назвал бы нижний. Они действуют на неявный параметр объекта; именующий ref-qualifier связывается с ссылкой lvalue и rvalue ref-qualifier привязывается к ссылке rvalue (функции, которые не принимают параметр как lvalue reference, но пусть он привязывается к любому). Обратите внимание, что они фактически не изменяют этот тип.