C ++ Boost перегружен шаблон функции - PullRequest
9 голосов
/ 19 мая 2010

Я не могу понять, почему этот сегмент выдает ошибку неразрешенной перегруженной функции (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>);
}

Ответы [ 3 ]

6 голосов
/ 21 мая 2010

Обновление: это ошибка 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 bug - Если вы снова посмотрите на заголовок stl_algobase.h, вы увидите, что есть два шаблона с именем max, версия с двумя параметрами и версия с одним параметром. Это не должно быть проблемой с вашим кодом, правда? Термин &max<int> должен обозначать версию с одним параметром и принимать ее адрес. Однако этого не происходит. Вы можете увидеть проблему в сокращенном (без заголовка) тесте:

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;
}

Приведенный выше код приводит к unresolved overloaded function type с gcc 4.3.4. Исправление заключается в удалении определения template <class T, class C> max(...){...} или добавлении static_cast<const int& (*)(const int&, const int&)>(...) вокруг адреса функции. Я предполагаю, что проблема связана с неправильным применением частичной явной спецификации параметров, которая указана в стандарте. Это позволяет вам не использовать конечные параметры шаблона для таких вещей, как указание типа возвращаемого значения, а не типов аргументов. То есть компилятор создает оба шаблона, когда он должен создавать только полностью указанный шаблон. Хотя это спорная гипотеза, поскольку ошибка была исправлена ​​в gcc> = 4.4.

Так как не следует взламывать stl_algobase.h;), работа вокруг Висенте предполагает, что он правильный, а именно приведение указателя функции к нужному типу указателя функции const int& (*)(const int&, const int&). В вашем коде приведение не работает, потому что, как указывает GMan, вы приводите к boost :: function <...>, который ничего не делает для устранения неоднозначности указателя на функцию.

5 голосов
/ 19 мая 2010

Чтобы критиковать код, нет причины для 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-арные классы предназначены для поддержки старых компиляторов.

3 голосов
/ 20 мая 2010

Кажется, проблема в определении шаблонной функции std :: max с выпусками gcc <4.4 </p>

С 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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...