2017-08-07 25 views
5

Tôi đã cố gắng biên dịch a project được viết chống lại Boost 1.55 so với Boost 1.63 mới hơn và tôi đang gặp lỗi thực sự lạ liên quan đến bind/function. Dưới đây là hoàn tất, đơn giản trường hợp thử nghiệm:Thay đổi hành vi lạ trong hàm boost :: bind/boost :: kể từ 1.55

#include <boost/bind.hpp> 
#include <boost/function.hpp> 

template < typename Arg1 = int, typename Arg2 = int, typename Arg3 = int > 
class foo 
{ 
public: 
    using function_t = boost::function3< void, Arg1, Arg2, Arg3 >; 

    void set_function(function_t f) 
    { 
    func_ = f; 
    } 

private: 
    function_t func_; 
}; 

class bar 
{ 
public: 
    bar() 
    { 
    foo_.set_function(boost::bind(&bar::func, this, _1, _2)); 
    } 

private: 
    void func(int const&, int&) {} 

    foo< int, int > foo_; 
}; 

int main() 
{ 
    bar x; 
    return 0; 
} 

... và một số đoạn chọn các lỗi tôi nhận được:

/usr/include/boost/bind/bind.hpp:398:35: error: no match for call to ‘(boost::_mfi::mf2<void, bar, const int&, int&>) (bar*&, int, int)’ 
/usr/include/boost/bind/mem_fn_template.hpp:278:7: note: candidate: R boost::_mfi::mf2<R, T, A1, A2>::operator()(T*, A1, A2) const [with R = void; T = bar; A1 = const int&; A2 = int&] <near match> 
/usr/include/boost/bind/mem_fn_template.hpp:278:7: note: conversion of argument 3 would be ill-formed: 
/usr/include/boost/bind/bind.hpp:398:35: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’ 
/usr/include/boost/bind/mem_fn_template.hpp:283:25: note: candidate: template<class U> R boost::_mfi::mf2<R, T, A1, A2>::operator()(U&, A1, A2) const [with U = U; R = void; T = bar; A1 = const int&; A2 = int&] 
/usr/include/boost/bind/mem_fn_template.hpp:283:25: note: template argument deduction/substitution failed: 
/usr/include/boost/bind/bind.hpp:398:35: note: cannot convert ‘(& a)->boost::_bi::rrlist3<int, int, int>::operator[](boost::_bi::storage3<boost::_bi::value<bar*>, boost::arg<1>, boost::arg<2> >::a3_)’ (type ‘int’) to type ‘int&’ 
/usr/include/boost/bind/mem_fn_template.hpp:291:25: note: candidate: template<class U> R boost::_mfi::mf2<R, T, A1, A2>::operator()(const U&, A1, A2) const [with U = U; R = void; T = bar; A1 = const int&; A2 = int&] 
/usr/include/boost/bind/mem_fn_template.hpp:291:25: note: template argument deduction/substitution failed: 
/usr/include/boost/bind/bind.hpp:398:35: note: cannot convert ‘(& a)->boost::_bi::rrlist3<int, int, int>::operator[](boost::_bi::storage3<boost::_bi::value<bar*>, boost::arg<1>, boost::arg<2> >::a3_)’ (type ‘int’) to type ‘int&’ 
/usr/include/boost/bind/mem_fn_template.hpp:299:7: note: candidate: R boost::_mfi::mf2<R, T, A1, A2>::operator()(T&, A1, A2) const [with R = void; T = bar; A1 = const int&; A2 = int&] 
/usr/include/boost/bind/mem_fn_template.hpp:299:7: note: no known conversion for argument 1 from ‘bar*’ to ‘bar&’ 

Nếu tôi thử trên một máy tính mà có Tăng 1,55, nó biên dịch bình thường. (Dự án cũng được biên dịch trên cùng một máy khi chỉ vào một bản dựng của Boost 1.55, do đó, vấn đề dường như không phải là trình biên dịch.) Vì vậy, dường như một cái gì đó đã thay đổi trong Tăng đó là mới gây ra điều này để thất bại.

Tôi không viết mã này, không phải là tôi quen thuộc với ruột của boost::functionboost::bind. Nếu ai đó có thể giải thích cho tôi lý do tại sao điều này là phá vỡ với Boost mới hơn, và hoặc là a) làm thế nào để sửa chữa nó, hoặc b) tại sao mã trên bị hỏng, nó sẽ được nhiều đánh giá cao!

Trả lời

6

Vấn đề là boost::function đã trở nên chặt chẽ hơn trong việc khớp chữ ký chức năng (tôi cho rằng phải khớp chặt chẽ hơn với hành vi của std::function). Tuy nhiên, hàm của bạn được khai báo là boost::function3< void, Arg1, Arg2, Arg3 >, hàm mà bạn đang ràng buộc với hàm này mất int const&int&.

Có một số cách để khắc phục sự cố này. Bạn có thể:

  1. Thay đổi bản tóm tắt là foo<int, int> trong bar thành foo<int const&, int&>.
  2. Thay đổi tuyên bố là function_t thành boost::function3<void, Arg1, Arg2 const&, Arg3&>.
  3. Thay đổi chữ ký của bar::func để chấp nhận đối số của nó theo giá trị.
+0

Cảm ơn. Tôi muốn nói (3) là không thể vì tham số phiền hà là tham số đầu ra, nhưng đào sâu hơn, AFAICT a) mã thực tế sử dụng mẫu này không thể tạo tham số tham chiếu hợp lệ để tham số cuối cùng gọi hàm được lưu trữ, và b) loại thực tế là một vùng chứa tham chiếu, và như vậy DTRT thậm chí sẽ được chuyển qua giá trị/bản sao. Vì vậy, AFAICT, (3) là trên thực tế sửa chữa chính xác cho mã thực. (Lưu ý cho bản ghi: các đối số 'const &' vẫn có thể được điều chỉnh; chỉ tham số tham chiếu cần phải thay đổi.) – Matthew