【问题标题】:Why the following code compiles with `c++03` but not with `c++11`为什么下面的代码可以用 `c++03` 编译,但不能用 `c++11`
【发布时间】:2016-07-22 23:54:23
【问题描述】:

我在这个小小的 mwe 中使用 boost::python 库。

#include <deque>
#include <boost/python.hpp>

typedef std::deque<long unsigned int>  DequeUInt64;

BOOST_PYTHON_MODULE_INIT(tmp) {

boost::python::class_<DequeUInt64>("DequeUInt64")
  .def("push_back"  ,&DequeUInt64::push_back)
  .def("push_front" ,&DequeUInt64::push_front);

} 

我观察到上面的代码可以使用std=c++03gnu++03 编译,但不能使用c++11c++0x。错误是:

tmp.cpp: In function 'void init_module_tmp()':
tmp.cpp:8:47: error: no matching function for call to 'boost::python::class_<std::deque<long unsigned int> >::def(const char [10], <unresolved overloaded function type>)'
     .def("push_back"  ,&DequeUInt64::push_back)
                                               ^
In file included [from /opt/local/include/boost/python.hpp:18:0], [from tmp.cpp:2]:
/opt/local/include/boost/python/class.hpp:223:11: 
   note: candidate: 
       template<class Derived> boost::python::class_<T, X1, X2, X3>::self& 
                               boost::python::class_<T, X1, X2, X3>::def(const boost::python::def_visitor<Derived>&) 
                               [with Derived = Derived; 
                                     W = std::deque<long unsigned int>; 
                                     X1 = boost::python::detail::not_specified; 
                                     X2 = boost::python::detail::not_specified; 
                                     X3 = boost::python::detail::not_specified]
       self& def(def_visitor<Derived> const& visitor)
       ^
   note:   template argument deduction/substitution failed:
tmp.cpp:8:47: 
   note:  mismatched types 'const boost::python::def_visitor<U>' and 'const char [10]'
          .def("push_back"  ,&DequeUInt64::push_back)
                                           ^
In file included [from /opt/local/include/boost/python.hpp:18:0], [from tmp.cpp:2]:
/opt/local/include/boost/python/class.hpp:233:11: 
   note: candidate: 
       template<class F> boost::python::class_<T, X1, X2, X3>::self& 
                         boost::python::class_<T, X1, X2, X3>::def(const char*, F) 
                         [with F = F; 
                               W = std::deque<long unsigned int>; 
                               X1 = boost::python::detail::not_specified; 
                               X2 = boost::python::detail::not_specified; 
                               X3 = boost::python::detail::not_specified]
     self& def(char const* name, F f)
       ^
   note:   template argument deduction/substitution failed:
tmp.cpp:8:47:
   note:   couldn't deduce template parameter 'F'
     .def("push_back"  ,&DequeUInt64::push_back)

我的 boost 是 boost: stable 1.60.0,我的 g++ 是 g++-mp-5 (MacPorts gcc5 5.4.0_0) 5.4.0。我可以看到,新标准不知何故导致类型/模板推断出现问题,但老实说,我真的不明白为什么?问题是因为 Boost 根本没有用 c++11 测试过吗?无论如何,上面的错误消息到底是什么意思?

【问题讨论】:

  • 只是出于好奇,Clang 有效吗?
  • 我很惊讶这个问题只有 2 票。除了标题含糊不清之外,这个问题包含了我想要的一切:一个实际的 MCVE、一个完整的编译器错误和上下文(Boost 和编译器版本)。

标签: c++ c++11 boost boost-python


【解决方案1】:

错误信息给你一个线索:

未解析的重载函数类型

你传入std::deque::push_back。查看reference,可以看到有两个重载:

void push_back( const T& value );
void push_back( T&& value ); // (since C++11)

C++11 添加了一个新的重载。因此,将指向 this 的指针作为参数传递变得无效。 push_front 也是如此。请注意,即使在 C++11 之前,实现也可以添加自己的重载[需要引用]

您可以将其转换为适当的类型:

.def("push_back"  ,static_cast<void(DequeUInt64::*)(DequeUInt64::const_reference)>(&DequeUInt64::push_back))
.def("push_front" ,static_cast<void(DequeUInt64::*)(DequeUInt64::const_reference)>(&DequeUInt64::push_front))

我转换它而不是根据 STL 的 Don't Help the Compiler 谈话明确指定模板参数。

根据 Tanner 的评论,如果您首先将其强制为函数指针,您也可以使用 lambda:

.def("push_back"  ,+[](DequeUInt64* d, DequeUInt64::const_reference x) { return d->push_back(x); })
.def("push_front" ,+[](DequeUInt64* d, DequeUInt64::const_reference x) { return d->push_front(x); })

【讨论】:

  • 或者传递一个 lambda 而不是难看的演员表。
  • @0x499602D2,我正要补充:)
  • def() 不接受 lambda,因为 Boost.Python 不知道如何推断签名。考虑使用+ 运算符将其转换为函数指针(例如+[](...){ ... })。 (demo)
  • @TannerSansbury,很高兴知道,谢谢。有趣的是它不接受它们,这意味着它也不应该接受仿函数。
【解决方案2】:

问题在于 C++11 为 push_back 添加了重载以支持移动语义,即 void push_front( T&amp;&amp; value );

所以编译器不知道选择哪一个 (&lt;unresolved overloaded function type&gt;)。你必须把它拼出来,像这样:

boost::python::class_<DequeUInt64>("DequeUInt64")
.def<void (DequeUInt64::*)( const T&)>("push_back",&DequeUInt64::push_back)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-09
    • 2019-08-21
    • 2010-10-24
    • 1970-01-01
    相关资源
    最近更新 更多