Возможно ли псевдоним boost :: make_iterator_range? - PullRequest
2 голосов
/ 15 декабря 2011

У меня проблемы с наложением алиасов на функцию boost::make_iterator_range

(Я хотел бы скрыть повышение за псевдонимом на случай, если эта конкретная библиотека будет принята в качестве стандарта в будущем.)

Есть ли способ заставить это работать?

#include <boost/range/iterator_range.hpp>

void Foo()
{
}

template< typename T >
void Bar()
{ }

template< typename T >
void Bar(char c)
{ }

void (&FooAlias)() = Foo;           // ok
void (&BarAlias)() = Bar<int>;      // ok

// boost::iterator_range<const size_t*> (&MakeIterRangeAlias)(const size_t*,const size_t*) = 
//  boost::make_iterator_range<const size_t*>;  // not ok

int main(int argc, char** argv)
{
    const size_t v[] = { 3, 5, 1, 5, 29, 15 };

    boost::iterator_range<const size_t*> r 
        = boost::make_iterator_range( std::begin( v ), std::end( v )); // want to alias this

    return 0;
}

Сообщение об ошибке:

In file included from /usr/include/boost/iterator/iterator_categories.hpp:15:0,
                 from /usr/include/boost/iterator/detail/facade_iterator_category.hpp:7,
                 from /usr/include/boost/iterator/iterator_facade.hpp:14,
                 from /usr/include/boost/range/iterator_range_core.hpp:23,
                 from /usr/include/boost/range/iterator_range.hpp:13,
                 from sandbox.cpp:2:
/usr/include/boost/mpl/eval_if.hpp: In instantiation of ‘boost::mpl::eval_if_c<true, boost::range_const_iterator<const long unsigned int*>, boost::range_mutable_iterator<const long unsigned int* const> >’:
/usr/include/boost/range/iterator.hpp:63:63:   instantiated from ‘boost::range_iterator<const long unsigned int* const>’
sandbox.cpp:20:10:   instantiated from here
/usr/include/boost/mpl/eval_if.hpp:60:31: error: no type named ‘type’ in ‘boost::mpl::eval_if_c<true, boost::range_const_iterator<const long unsigned int*>, boost::range_mutable_iterator<const long unsigned int* const> >::f_ {aka struct boost::range_const_iterator<const long unsigned int*>}’
/usr/include/boost/mpl/eval_if.hpp: In instantiation of ‘boost::mpl::eval_if_c<false, boost::range_const_iterator<const long unsigned int*>, boost::range_mutable_iterator<const long unsigned int*> >’:
/usr/include/boost/range/iterator.hpp:63:63:   instantiated from ‘boost::range_iterator<const long unsigned int*>’
sandbox.cpp:20:10:   instantiated from here
/usr/include/boost/mpl/eval_if.hpp:60:31: error: no type named ‘type’ in ‘boost::mpl::eval_if_c<false, boost::range_const_iterator<const long unsigned int*>, boost::range_mutable_iterator<const long unsigned int*> >::f_ {aka struct boost::range_mutable_iterator<const long unsigned int*>}’
sandbox.cpp:20:10: error: invalid initialization of non-const reference of type ‘void (&)(const size_t*, const size_t*) {aka void (&)(const long unsigned int*, const long unsigned int*)}’ from an rvalue of type ‘<unresolved overloaded function type>’
make: *** [sandbox] Error 1

1 Ответ

5 голосов
/ 15 декабря 2011

Использование указателей на функции является неоптимальным способом псевдонима функции. Он не такой гибкий, как оригинал (он больше не может быть шаблоном), и теперь вам нужно знать точную сигнатуру функции, которая может быть или не быть стабильной.
Вместо этого попробуйте этот подход.

template< typename ... Args >
auto MakeIterRangeAlias( Args&& ... args ) -> decltype( /* copy return line here */ )
{
   return boost::make_iterator_range( std::forward<Args>(args)... );
}

Почти без работы с вашей стороны псевдоним поддерживает точную подпись оригинала. Даже если это резко изменится, вы все равно настроены. Кроме того, в отличие от подхода с указателем на функцию, оптимизатор сможет тривиально встроить MakeIterRangeAlias, чтобы не было накладных расходов времени выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...