Проблема с указателем на функцию-член при использовании стандартных библиотечных методов
Этот вопрос возник из
Передача указателя на функцию-член в перегруженный метод класса в шаблонную функцию.
Вам не нужно читать это, чтобы понять этот вопрос. Вероятно, оба вопроса будут иметь одинаковый ответ.
я получаюошибка компилятора для простого кода ниже.
#include<set>
template<typename Return, typename T>
T ReceiveFuncPtr (Return (T::*Method)(const int&))
{
T obj; // Found and declared an object of actual container class
(obj.*Method)(1); // Some processing
return obj; // Returned that container class object with RVO
}
int main ()
{
ReceiveFuncPtr(&std::set<int>::insert); // ERROR
}
Интересна ошибка:
In function 'int main()':
error: no matching function for call to 'ReceiveFuncPtr(<unresolved overloaded function type>)'
ReceiveFuncPtr(&std::set<int>::insert); // ERROR
^
note: candidate is:
note: template<class Return, class T> T ReceiveFuncPtr(Return (T::*)(const int&))
T ReceiveFuncPtr (Return (T::*Method)(const int&))
^
note: template argument deduction/substitution failed:
note: mismatched types 'const int&' and 'std::initializer_list<int>'
ReceiveFuncPtr(&std::set<int>::insert); // ERROR
^
note: mismatched types 'const int&' and 'std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}'
note: mismatched types 'const int&' and 'std::set<int>::const_iterator {aka std::_Rb_tree_const_iterator<int>}'
note: mismatched types 'const int&' and 'std::set<int>::value_type&& {aka int&&}'
note: couldn't deduce template parameter 'Return'
Если вы посмотрите нанотаПосле этого выясняется, что компилятор сопоставляет все остальные методы, кроме правильного! В этом случае компилятор должен был соответствоватьinsert(const std::set<int>::value_type&)
акаconst int&
, Если я изменюReceiveFuncPtr()
чтобы соответствовать некоторой другой перегрузке, он снова потерпит неудачу, пропустив эту перегрузку.
Чтобы отладить эту ситуацию, я создал версиюstd::set
, Но этокомпилирует нормально:
template<typename T, typename T2 = void>
struct MySet
{
std::pair<T,bool> insert (const T& i) { return std::pair<T,bool>(T(),true); }
std::pair<T,bool> insert (T&& i) { return std::pair<T,bool>(T(),true); }
void insert (std::initializer_list<T> i) { return false; }
}
int main ()
{
ReceiveFuncPtr(&MySet<int>::insert); // OK
}
После серфинга я наткнулся на этот пост:
Каковы правила для указателей на функции и указателей на функции-члены для стандартных функций?
Хотя это связано, это не решает проблему.
Вопрос: Почему замена функции-члена завершается неудачно в случае стандартного метода библиотеки, когда то же самое относится и к рукописному методу класса
Обновить:
Посмотрев на правильный ответ, я уверен, чтоinsert
не может быть использован. Единственным способом было бы ужасное приведение типов, которое является излишним для этой проблемы.
Один элегантныйрешение это использоватьstd::set<int>::emplace<const int&>
который имеет толькоtemplate
d версия в отличие от вставки, которая имеет смесьtemplate
и неtemplate
версии.
Вызовите функцию, как показано ниже:
ReceiveFuncPtr(&std::set<int>::emplace<const int&>);