Функция повышения C++ перегруженный шаблон

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

3 ответа

Обновление: это ошибка 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. Исправление заключается либо в удалении шаблона max(...){...} определения, либо в добавлении static_cast(...) вокруг адреса функции. Я предполагаю, что проблема связана с неправильным применением частичной явной спецификации параметров, которая определена стандартом. Она позволяет не указывать параметры шаблона в конце, чтобы сделать что-то вроде указания типа возвращаемого значения, а не типа аргументов. То есть компилятор инстанцирует оба шаблона, когда должен инстанцировать только полностью указанный шаблон. Впрочем, это спорный вопрос, поскольку ошибка исправлена в gcc >= 4.4.

Поскольку не стоит хакать stl_algobase.h ;)

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

6
ответ дан 4 December 2019 в 14:26
поделиться

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

5
ответ дан 4 December 2019 в 14:26
поделиться

Похоже, проблема с определением шаблонной функции 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
}
3
ответ дан 4 December 2019 в 14:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: