[Boost-bugs] [Boost C++ Libraries] #10990: cpp_rational is not nothrow move constructible

Subject: [Boost-bugs] [Boost C++ Libraries] #10990: cpp_rational is not nothrow move constructible
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-02-02 21:40:39


#10990: cpp_rational is not nothrow move constructible
-------------------------------------------------+-------------------------
 Reporter: Taras Morozovsky | Owner: johnmaddock
  <taras.morozovsky@…> | Status: new
     Type: Bugs | Component:
Milestone: To Be Determined | multiprecision
  Version: Boost 1.57.0 | Severity: Problem
 Keywords: multiprecision cpp_rational move |
  constructor noexcept |
  is_nothrow_move_constructible |
  rational_adaptor |
-------------------------------------------------+-------------------------
 boost::multiprecision::cpp_rational's move constructor is not noexcept.
 This does not allow programmers to make objects containing a cpp_rational
 data member nothrow move constructible. Maybe that's not a severe bug, but
 an inconvenience at least.

 #include <iostream>
 #include <iomanip>
 #include <type_traits>
 #include <boost/multiprecision/cpp_int.hpp>
 int main()
 {
     using namespace std;
     using namespace boost::multiprecision;
     cout << boolalpha;
     cout << is_nothrow_move_constructible<cpp_int>::value << endl;
     cout << is_nothrow_move_assignable<cpp_int>::value << endl;
     cout << is_nothrow_move_constructible<cpp_rational>::value << endl;
     cout << is_nothrow_move_assignable<cpp_rational>::value << endl;
 }

 Outputs:
 true
 true
 false
 true

 I believe there is a problem in rational_adaptor (see
 <rational_adaptor.hpp>, line 60), since its move constructor is defined as
 follows:

 rational_adaptor(rational_adaptor&& o) : m_value(o.m_value) {}

 Here, o.m_value is treated like an lvalue despite it can be moved from.
 Thus new object's m_value is copy-constructed, not move-constructed. That
 does not allow cpp_rational's move constructor to be noexcept (it is
 noexcept only if its backend class has a noexcept move ctor), also it may
 lead to some minor loss of efficiency.

 This problem can be fixed by rewriting mentioned rational_adaptor's move
 constructor this way:
    rational_adaptor(rational_adaptor&& o)
 BOOST_NOEXCEPT_IF(noexcept(rational_type(std::declval<rational_type>())))
       : m_value(static_cast<rational_type&&>(o.m_value)) {}

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/10990>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:17 UTC