Выведены конфликтующие типы для универсальной ссылки и указателя на член
Я хочу такую функцию:
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);
}