簡體   English   中英

為什么在C ++ 0x模式下將boost :: move()的返回值分配給非const引用失敗,但是在C ++ 03模式下卻有效

[英]Why does assigning the return value of boost::move() to a non-const reference fails in C++0x mode but works in C++03 mode

這是可用於重現此問題的源代碼:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/move/move.hpp>
#include <boost/ref.hpp>

std::ostream& dump_to_stream(std::ostream& os, int a, int b) {
  return os << a << '\n' << b << '\n';
}

template <class R, class F>
R call_under_lock(F f) {
  // lock();
  R r = f();
  // unlock();
  return boost::move(r);
}

int main() {
  std::ostream& os = call_under_lock<std::ostream&>(
    boost::bind(&dump_to_stream, boost::ref(std::cout), 1, 2));
}

在GCC中使用C ++ 03模式時,代碼可以毫無問題地編譯。 另一方面,使用C ++ 0x模式會產生以下錯誤:

$ g++ -I../../boost_latest -std=c++0x -O2 -Wall -Wextra   -c -o test.o test.cpp
(...)
test.cpp: In function ‘R call_under_lock(F) [with R = std::basic_ostream<char>&, F = boost::_bi::bind_t<std::basic_ostream<char>&, std::basic_ostream<char>& (*)(std::basic_ostream<char>&, int, int), boost::_bi::list3<boost::reference_wrapper<std::basic_ostream<char> >, boost::_bi::value<int>, boost::_bi::value<int> > >]’:
test.cpp:20:62:   instantiated from here
test.cpp:15:23: error: invalid initialization of non-const reference of type ‘std::basic_ostream<char>&’ from an rvalue of type ‘boost::remove_reference<std::basic_ostream<char>&>::type {aka std::basic_ostream<char>}’
(...)

這種失敗的原因是什么? 有沒有辦法在C ++ 11模式下解決該問題?

上面提供的代碼是我在通用代碼中使用的簡化版。 因此,需要這樣的組合( boost::move +非常量ref作為返回值類型)。

我使用gcc v4.6.3,Boost 1.54.0和Ubuntu 12.04(i386)。

更新1:我使測試用例更加實際。 目標是要有一個泛型函數,該函數在鎖下調用函子,並通過boost :: move()返回函子返回的值,因為返回值的類型可能是可移動的,但不可復制(在某些情況下確實如此)我對call_under_lock()調用。

更新2:事實證明,在C ++ 11模式下使用clang 3.5.1~(exp)時,可以觀察到類似的問題:

$ clang test.cpp -I../../boost_latest/ -lstdc++ --std=c++11
test.cpp:11:10: error: non-const lvalue reference to type 'basic_ostream<[2 * ...]>' cannot bind to a temporary of type 'basic_ostream<[2 * ...]>'
  return boost::move(r);
         ^~~~~~~~~~~~~~
test.cpp:19:22: note: in instantiation of function template specialization 'call_under_lock<std::basic_ostream<char> &, boost::_bi::bind_t<std::basic_ostream<char> &, std::basic_ostream<char> &(*)(std::basic_ostream<char> &, int, int),
      boost::_bi::list3<boost::reference_wrapper<std::basic_ostream<char> >, boost::_bi::value<int>, boost::_bi::value<int> > > >' requested here
  std::ostream& os = call_under_lock<std::ostream&>(

更新3:此主題也已在boost-users郵件列表[1]上進行了討論。

[1] http://boost.2283326.n4.nabble.com/move-differences-between-results-in-C-03-and-C-11-modes-td4659264.html

這種失敗的原因是什么?

在C ++ 03中,R是std::ostream& ,而boost::move()顯然返回相同的類型,因此沒有問題。

在C ++ 11中,R仍然是std::ostream& ,但是boost::move()將返回std::ostream&& 這使表達式boost::move()成為一個右值,該右值不能綁定到非常量左值引用。

有沒有辦法在C ++ 11模式下解決該問題?

是:

template <class R, class F>
R call_under_lock(F f) {
  // lock();
  R r = f();
  // unlock();
  return r;
}

這應該完全符合C ++ 03和C ++ 11的要求。 它會在您需要時移動,而在您不需要時不會移動。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM