Выведены конфликтующие типы для универсальной ссылки и указателя на член

Я хочу такую ​​функцию:

template<typename C, typename T>
void foo(C &&aclass, T (C::*const memberFunc)(unsigned)) {

}

Параметры (на словах, потому что синтаксис типа C/C++ является ментальным):

  • Универсальная ссылка на класс, например MyClass,
  • Постоянный указатель на функцию-член MyClass который принимает неподписанный int и возвращает T,

Это работает, однако, если я вызываю его со ссылкой на l-значение в качестве первого параметра, я получаю сообщение об ошибке:

шаблон кандидата игнорируется: обнаружены конфликтующие типы для параметра "C" ("MyClass &" против "MyClass")

Насколько я понимаю, это выводит C из первого и второго параметров, но придумывает разные выводы и запутывается.

В соответствии с этим ответом вы можете только сделать вывод по первому параметру и как-то использовать typename Ключевое слово по второму параметру. Но я не могу выработать синтаксис, чтобы сделать это, когда я хочу, чтобы он выводил один из типов в параметре (T), но не другой (C).

Этот ответ также полезен, но они решают его, просто не используя ссылки для C вообще, что в таком случае одинаково эффективно, но не по моему.

Это возможно?

2 ответа

Решение

Со значениями C будет выведен как тип lvalue-reference (т.е. MyClass & для вашего случая) для 1-го параметра, который является ожидаемым поведением ссылки на пересылку; Вы можете удалить ссылку через std::remove_reference при использовании C во 2-м параметре, например

template<typename C, typename T>
void foo(C &&aclass, T (std::remove_reference_t<C>::*const memberFunc)(unsigned)) {

}

И, как указал @Quentin, использование std::remove_reference также вводит не выводимый контекст, который бы предотвращал C от вывода из 2-го параметра.

На самом деле я только что обнаружил, что универсальная ссылочная перегрузка пересылает его в эталонную версию с l-значением. Не особенно элегантный, хотя; Я чувствую, что должен быть лучший способ.

template<typename C, typename T>
void foo(C &aclass, T (C::*const memberFunc)(unsigned)) {
  // Code goes here.
}

template<typename C, typename T>
void foo(C &&aclass, T (C::*const memberFunc)(unsigned)) {
  foo(aclass, memberFunc);
}
Другие вопросы по тегам