【问题标题】:Is it possible to alias boost::make_iterator_range?是否可以别名 boost::make_iterator_range?
【发布时间】:2011-12-15 05:58:16
【问题描述】:

我在为函数 boost::make_iterator_range 起别名时遇到问题

(我想将 boost 隐藏在别名后面,以防将来某个特定库被采用为标准。)

有什么办法可以让它发挥作用吗?

#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

【问题讨论】:

  • 我看到的第一个问题是别名的返回类型错误(应该是boost::iterator_range&lt;const size_t*&gt;,而不是void)。
  • make_iterator_range 的第二个参数应该是 &amp;v[n]。它应该指向最后一个元素之后的元素。由于您已标记 [c++11],请使用 std::beginstd::end 以避免计算 n
  • @Mankarse +1 优点:OP 已修改
  • @KennyTM +1 你是对的:OP 已修改

标签: c++ boost iterator c++11


【解决方案1】:

使用函数指针是对函数进行别名的次优方式。它不像原来那样灵活(它不再是模板),您现在需要知道函数的确切签名,它可能稳定也可能不稳定。
而是尝试这种方法。

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

在您几乎没有任何工作的情况下,别名支持原件的确切签名。即使它发生了巨大的变化,你仍然准备好了。此外,与函数指针方法不同,优化器将能够简单地内联 MakeIterRangeAlias,从而没有运行时开销。

【讨论】:

  • @deft-code 很棒的建议,但我无法让它工作。即使在填写了 decltype() 之后,如果我取出模板参数中的 T,它也会编译,但是对 MakeIterRangeAlias 的调用无法正确绑定。我正在使用 gcc 4.6.1
  • @kfmfe04:对不起,当您提交代码而不编译它时会发生这种情况。这是使用std::make_pair 代替ideone.com/XVTxa 的工作概念证明
  • @deft-code - woohoo - 现在效果很好 - 也感谢让我进入可变参数模板
猜你喜欢
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 2012-06-02
  • 1970-01-01
  • 2011-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多