Я не могу выяснить, почему этот сегмент дает неразрешенную ошибку перегруженной функции (gcc версия 4.3.4 (Debian 4.3.4-6)):
#include <algorithm>
#include <boost/function.hpp>
// this does not work
int main1()
{
typedef boost::function<const int&(const int&, const int&)> max;
max m(&std::max<int>);
}
// this does not work
int main2() {
typedef boost::function2<const int&, const int&, const int&> max;
max m(static_cast<max>(&std::max<int>));
}
можно ли помочь мне, спасибо
test.cpp: In function âint main()â:
test.cpp:7: error: no matching function for call to âboost::function2<const int&, const int&, const int&>::function2(<unresolved overloaded function type>)â
/usr/include/boost/function/function_template.hpp:747: note: candidates are: boost::function2<R, T1, T2>::function2(const boost::function2<R, T1, T2>&) [with R = const int&, T0 = const int&\
, T1 = const int&]
/usr/include/boost/function/function_template.hpp:739: note: boost::function2<R, T1, T2>::function2(boost::function2<R, T1, T2>::clear_type*) [with R = const int&, T0 = cons\
t int&, T1 = const int&]
/usr/include/boost/function/function_template.hpp:707: note: boost::function2<R, T1, T2>::function2() [with R = const int&, T0 = const int&, T1 = const int&]
макс. / минута определяется как
template<typename _Tp>
inline const _Tp&
max(const _Tp& __a, const _Tp& __b)
{
// concept requirements
__glibcxx_function_requires(_LessThanComparableConcept<_Tp>)
//return __a < __b ? __b : __a;
if (__a < __b)
return __b;
return __a;
}
Я попробовал все виды шаблона явное инстанцирование, но ничто, кажется, не работает. Та же проблема появляется с g ++ 4.1, но не с ICC
это работает
#include <algorithm>
#include <boost/function.hpp>
namespace std_ {
template<typename _Tp>
inline const _Tp&
max(const _Tp& __a, const _Tp& __b)
{
// concept requirements
//return __a < __b ? __b : __a;
if (__a < __b)
return __b;
return __a;
}
}
int main()
{
typedef const int &T;
typedef boost::function<T(T,T)> min_;
//typedef const int&(*min_)(const int&, const int&);
min_ m(::std_::max<int>);
}
и это
#include <algorithm>
#include <boost/function.hpp>
int main()
{
//typedef const int &T;
//typedef boost::function<T(T,T)> min_;
typedef const int&(*min_)(const int&, const int&);
min_ m(::std::max<int>);
}
Обновление: это ошибка gcc, которая была исправлена в gcc >=4.4. bugzilla. Также, пересмотрел свой ответ с уменьшенным тестовым примером.
В этой проблеме есть два компонента: способ, которым boost::function принимает указатель функции, и ошибка gcc.
boost::function - Есть что-то странное в сообщении об ошибке, которое вы перечислили в вопросе; нет никакого конструктора-кандидата, который принимает что-то похожее на адрес функции. Покопавшись в boost::function src, можно найти соответствующий конструктор (опустив аргумент enable_if):
template<typename Functor>
function(Functor f) : base_type(f) {}
Итак, boost::function совсем не помогает вам в определении типа указателя функции; если функция перегружена, то адрес должен быть приведен для определения ее типа. Если используется адрес перегруженной функции, то приведенный выше шаблон не может быть инстанцирован, и поэтому соответствующий конструктор не появляется в сообщении об ошибке.
ошибка gcc - Если вы снова посмотрите на заголовок stl_algobase.h, то увидите, что там есть два шаблона с именем max, версия с двумя параметрами и версия с одним параметром. Однако это не должно быть проблемой для вашего кода, верно? Термин &max
должен инстанцировать версию с одним параметром и взять ее адрес. Однако этого не происходит. Вы можете увидеть проблему в сокращенном (без заголовка) тестовом примере:
template <class T>
const T& max(const T& x, const T& y){
return x > y ? x : y;
}
template <class T, class C>
const T& max(const T& x, const T& y, C comp){
return comp(x, y) ? y : x;
}
template <class R, class A0, class A1>
struct functor{
template <class F>
functor(F f) : f(f) {}
R (*f)(A0, A1);
};
int main(void){
functor<const int&, const int&, const int&> func(&max<int>);
return 0;
}
Приведенный выше код приводит к неразрешенному типу перегруженной функции
с gcc 4.3.4. Исправление заключается либо в удалении шаблона
определения, либо в добавлении static_cast
вокруг адреса функции. Я предполагаю, что проблема связана с неправильным применением частичной явной спецификации параметров, которая определена стандартом. Она позволяет не указывать параметры шаблона в конце, чтобы сделать что-то вроде указания типа возвращаемого значения, а не типа аргументов. То есть компилятор инстанцирует оба шаблона, когда должен инстанцировать только полностью указанный шаблон. Впрочем, это спорный вопрос, поскольку ошибка исправлена в gcc >= 4.4.
Поскольку не стоит хакать stl_algobase.h ;)
Так как не стоит хакать stl_algobase.h ;), то правильным будет решение, предложенное Vicente, а именно приведение указателя функции к нужному типу указателя функции const int& (*)(const int&, const int&)
. В вашем коде приведение не работает, потому что, как указывает GMan, вы приводите к boost::function<...>, что никак не разрешает двусмысленность указателя функции.
Чтобы критиковать код, нет причин static_cast
это делать. Учитывайте, что все, что собирается сделать каст, это использовать конструктор boost::function2
для создания новой boost::function2
, затем она будет скопирована в m
. Просто конструируйте непосредственно в m
:
#include <algorithm>
#include <boost/function.hpp>
int main()
{
typedef boost::function2<const int&, const int&, const int&> max;
max m(&std::max<int>);
}
Наконец, предпочтительным синтаксисом boost::function
является:
#include <algorithm>
#include <boost/function.hpp>
int main()
{
typedef boost::function<const int&(const int&, const int&)> max;
max m(&std::max<int>);
}
Специфические классы n-ary предназначены для поддержки старых компиляторов.
Похоже, проблема с определением шаблонной функции std::max в релизах gcc < 4.4
С gcc-4.4.0 и msvc Express9 это работает.
Следующее работает также для gcc-3.4 и gcc-4.3
int main1()
{
int res = std::max(1,2);
typedef boost::function<const int&(const int&, const int&)> max;
max m(static_cast<const int&(*)(const int&, const int&)>(std::max<int>));
return 0
}