diff --git a/bindings/python/src/bytes.hpp b/bindings/python/src/bytes.hpp index 8949bfe05..245583181 100644 --- a/bindings/python/src/bytes.hpp +++ b/bindings/python/src/bytes.hpp @@ -13,8 +13,8 @@ struct bytes bytes(std::string const& s): arr(s) {} bytes(std::string&& s): arr(std::move(s)) {} bytes(bytes const&) = default; - bytes(bytes&&) = default; - bytes& operator=(bytes&&) = default; + bytes(bytes&&) noexcept = default; + bytes& operator=(bytes&&) noexcept = default; bytes() {} std::string arr; }; diff --git a/bindings/python/src/converters.cpp b/bindings/python/src/converters.cpp index ac37d09f4..8ac3c1f8f 100644 --- a/bindings/python/src/converters.cpp +++ b/bindings/python/src/converters.cpp @@ -11,6 +11,7 @@ #include "libtorrent/units.hpp" #include "libtorrent/sha1_hash.hpp" #include "libtorrent/disk_interface.hpp" // for open_file_state +#include "libtorrent/aux_/noexcept_movable.hpp" #include using namespace boost::python; @@ -70,9 +71,10 @@ struct pair_to_tuple } }; +template struct address_to_tuple { - static PyObject* convert(lt::address const& addr) + static PyObject* convert(Addr const& addr) { lt::error_code ec; return incref(bp::object(addr.to_string(ec)).ptr()); @@ -145,7 +147,7 @@ struct dict_to_map template struct vector_to_list { - static PyObject* convert(const std::vector& v) + static PyObject* convert(T const& v) { list l; for (int i = 0; i < int(v.size()); ++i) @@ -162,7 +164,7 @@ struct list_to_vector list_to_vector() { converter::registry::push_back( - &convertible, &construct, type_id>() + &convertible, &construct, type_id() ); } @@ -174,17 +176,17 @@ struct list_to_vector static void construct(PyObject* x, converter::rvalue_from_python_stage1_data* data) { void* storage = ((converter::rvalue_from_python_storage< - std::vector>*)data)->storage.bytes; + T>*)data)->storage.bytes; - std::vector p; + T p; int const size = int(PyList_Size(x)); p.reserve(size); for (int i = 0; i < size; ++i) { object o(borrowed(PyList_GetItem(x, i))); - p.push_back(extract(o)); + p.push_back(extract(o)); } - std::vector* ptr = new (storage) std::vector(); + T* ptr = new (storage) T(); ptr->swap(p); data->convertible = storage; } @@ -234,22 +236,39 @@ void bind_converters() to_python_converter, pair_to_tuple>(); to_python_converter>(); to_python_converter>(); - to_python_converter(); + to_python_converter>(); to_python_converter, pair_to_tuple>(); - to_python_converter, vector_to_list>(); - to_python_converter, vector_to_list>(); - to_python_converter, vector_to_list>(); - to_python_converter, vector_to_list>(); - to_python_converter, vector_to_list>(); - to_python_converter, vector_to_list>(); - to_python_converter, vector_to_list>(); - to_python_converter, vector_to_list>(); - to_python_converter>, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter, vector_to_list>>(); + to_python_converter>, vector_to_list>>>(); to_python_converter>(); to_python_converter>(); + // work-around types + to_python_converter, address_to_tuple< + lt::aux::noexcept_movable>>(); + to_python_converter, endpoint_to_tuple< + lt::aux::noexcept_movable>>(); + to_python_converter, endpoint_to_tuple< + lt::aux::noexcept_movable>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>, vector_to_list>>>(); + to_python_converter>>, vector_to_list>>>>(); + // python -> C++ conversions tuple_to_pair(); tuple_to_pair(); @@ -257,12 +276,20 @@ void bind_converters() tuple_to_endpoint(); tuple_to_pair(); dict_to_map(); - list_to_vector(); - list_to_vector(); - list_to_vector(); - list_to_vector(); - list_to_vector(); - list_to_vector>(); + list_to_vector>(); + list_to_vector>(); + list_to_vector>(); + list_to_vector>(); + list_to_vector>(); + list_to_vector>>(); + + // work-around types + list_to_vector>>(); + list_to_vector>>(); + list_to_vector>>(); + list_to_vector>>(); + list_to_vector>>(); + list_to_vector>>>(); to_strong_typedef(); to_strong_typedef(); diff --git a/include/libtorrent/Makefile.am b/include/libtorrent/Makefile.am index 0f8385eae..162a36858 100644 --- a/include/libtorrent/Makefile.am +++ b/include/libtorrent/Makefile.am @@ -207,6 +207,7 @@ nobase_include_HEADERS = \ aux_/typed_span.hpp \ aux_/array.hpp \ aux_/ip_notifier.hpp \ + aux_/noexcept_movable.hpp \ \ extensions/smart_ban.hpp \ extensions/ut_metadata.hpp \ diff --git a/include/libtorrent/add_torrent_params.hpp b/include/libtorrent/add_torrent_params.hpp index 637c80df2..ee2342f23 100644 --- a/include/libtorrent/add_torrent_params.hpp +++ b/include/libtorrent/add_torrent_params.hpp @@ -46,6 +46,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bitfield.hpp" #include "libtorrent/error_code.hpp" #include "libtorrent/units.hpp" +#include "libtorrent/aux_/noexcept_movable.hpp" namespace libtorrent { @@ -85,9 +86,9 @@ namespace libtorrent { // which determines the storage mechanism for the downloaded or seeding // data for the torrent. For more information, see the ``storage`` field. explicit add_torrent_params(storage_constructor_type sc = default_storage_constructor) - : storage(sc) {} - add_torrent_params(add_torrent_params&&) = default; - add_torrent_params& operator=(add_torrent_params&&) = default; + : storage(storage_constructor_type(sc)) {} + add_torrent_params(add_torrent_params&&) noexcept = default; + add_torrent_params& operator=(add_torrent_params&&) noexcept = default; add_torrent_params(add_torrent_params const&) = default; add_torrent_params& operator=(add_torrent_params const&) = default; @@ -285,18 +286,18 @@ namespace libtorrent { // If the torrent doesn't have a tracker, but relies on the DHT to find // peers, the ``trackers`` can specify tracker URLs for the torrent. - std::vector trackers; + aux::noexcept_movable> trackers; // the tiers the URLs in ``trackers`` belong to. Trackers belonging to // different tiers may be treated differently, as defined by the multi // tracker extension. This is optional, if not specified trackers are // assumed to be part of tier 0, or whichever the last tier was as // iterating over the trackers. - std::vector tracker_tiers; + aux::noexcept_movable> tracker_tiers; // a list of hostname and port pairs, representing DHT nodes to be added // to the session (if DHT is enabled). The hostname may be an IP address. - std::vector> dht_nodes; + aux::noexcept_movable>> dht_nodes; std::string name; @@ -321,7 +322,11 @@ namespace libtorrent { // or encrypt the content on disk for instance. For more information // about the storage_interface that needs to be implemented for a custom // storage, see storage_interface. +#ifdef __clang__ storage_constructor_type storage; +#else + aux::noexcept_movable storage; +#endif // The ``userdata`` parameter is optional and will be passed on to the // extension constructor functions, if any @@ -331,7 +336,7 @@ namespace libtorrent { // can be set to control the initial file priorities when adding a // torrent. The semantics are the same as for // ``torrent_handle::prioritize_files()``. - std::vector file_priorities; + aux::noexcept_movable> file_priorities; // torrent extension construction functions can be added to this vector // to have them be added immediately when the torrent is constructed. @@ -339,7 +344,7 @@ namespace libtorrent { // to avoid race conditions. For instance it may be important to have the // plugin catch events that happen very early on after the torrent is // created. - std::vector(torrent_handle const&, void*)>> + aux::noexcept_movable(torrent_handle const&, void*)>>> extensions; // the default tracker id to be used when announcing to trackers. By @@ -434,20 +439,20 @@ namespace libtorrent { // // url_seeds expects URLs to regular web servers, aka "get right" style, // specified in `BEP 19`_. - std::vector http_seeds; - std::vector url_seeds; + aux::noexcept_movable> http_seeds; + aux::noexcept_movable> url_seeds; // peers to add to the torrent, to be tried to be connected to as // bittorrent peers. - std::vector peers; + aux::noexcept_movable> peers; // peers banned from this torrent. The will not be connected to - std::vector banned_peers; + aux::noexcept_movable> banned_peers; // this is a map of partially downloaded piece. The key is the piece index // and the value is a bitfield where each bit represents a 16 kiB block. // A set bit means we have that block. - std::map unfinished_pieces; + aux::noexcept_movable> unfinished_pieces; // this is a bitfield indicating which pieces we already have of this // torrent. @@ -462,16 +467,16 @@ namespace libtorrent { // element in the vector represent the piece with the same index. If you // set both file- and piece priorities, file priorities will take // precedence. - std::vector piece_priorities; + aux::noexcept_movable> piece_priorities; // if this is a merkle tree torrent, and you're seeding, this field must // be set. It is all the hashes in the binary tree, with the root as the // first entry. See torrent_info::set_merkle_tree() for more info. - std::vector merkle_tree; + aux::noexcept_movable> merkle_tree; // this is a map of file indices in the torrent and new filenames to be // applied before the torrent is added. - std::map renamed_files; + aux::noexcept_movable> renamed_files; #ifndef TORRENT_NO_DEPRECATE // deprecated in 1.2 @@ -501,7 +506,7 @@ namespace libtorrent { // torrent_handle. See fast-resume_. The ``vector`` that is passed in // will be swapped into the running torrent instance with // ``std::vector::swap()``. - std::vector TORRENT_DEPRECATED_MEMBER resume_data; + aux::noexcept_movable> TORRENT_DEPRECATED_MEMBER resume_data; // to support the deprecated use case of reading the resume data into // resume_data field and getting a reject alert, any parse failure is @@ -514,11 +519,24 @@ namespace libtorrent { std::string deprecated5; std::string deprecated1; std::string deprecated2; - std::vector deprecated3; + aux::noexcept_movable> deprecated3; error_code deprecated4; #endif }; + + static_assert(std::is_nothrow_move_constructible::value + , "should be nothrow move constructible"); + + // TODO: pre C++17, GCC and msvc does not make std::string nothrow move + // assignable, which means no type containing a string will be nothrow move + // assignable by default either +// static_assert(std::is_nothrow_move_assignable::value +// , "should be nothrow move assignable"); + + // TODO: it would be nice if this was nothrow default constructible +// static_assert(std::is_nothrow_default_constructible::value +// , "should be nothrow default constructible"); } #endif diff --git a/include/libtorrent/alert.hpp b/include/libtorrent/alert.hpp index c75c941ff..b1371ff3e 100644 --- a/include/libtorrent/alert.hpp +++ b/include/libtorrent/alert.hpp @@ -76,7 +76,7 @@ namespace libtorrent { alert(alert const& rhs) = delete; alert& operator=(alert const&) = delete; - alert(alert&& rhs) = default; + alert(alert&& rhs) noexcept = default; #ifndef TORRENT_NO_DEPRECATE // only here for backwards compatibility diff --git a/include/libtorrent/alert_types.hpp b/include/libtorrent/alert_types.hpp index 2f707b82d..21d847db0 100644 --- a/include/libtorrent/alert_types.hpp +++ b/include/libtorrent/alert_types.hpp @@ -52,6 +52,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/escape_string.hpp" // for convert_from_native #include "libtorrent/string_view.hpp" #include "libtorrent/stack_allocator.hpp" +#include "libtorrent/aux_/noexcept_movable.hpp" #include "libtorrent/aux_/disable_warnings_push.hpp" #include @@ -72,7 +73,7 @@ namespace libtorrent { { // internal torrent_alert(aux::stack_allocator& alloc, torrent_handle const& h); - torrent_alert(torrent_alert&&) = default; + torrent_alert(torrent_alert&&) noexcept = default; // internal static const int alert_type = 0; @@ -103,7 +104,7 @@ namespace libtorrent { // internal peer_alert(aux::stack_allocator& alloc, torrent_handle const& h, tcp::endpoint const& i, peer_id const& pi); - peer_alert(peer_alert&&) = default; + peer_alert(peer_alert&& rhs) noexcept = default; static const int alert_type = 1; static const int static_category = alert::peer_notification; @@ -111,14 +112,14 @@ namespace libtorrent { virtual std::string message() const override; // The peer's IP address and port. - tcp::endpoint const endpoint; + aux::noexcept_movable endpoint; // the peer ID, if known. - peer_id const pid; + peer_id pid; #ifndef TORRENT_NO_DEPRECATE // The peer's IP address and port. - tcp::endpoint const ip; + aux::noexcept_movable ip; #endif }; @@ -144,11 +145,11 @@ namespace libtorrent { std::string TORRENT_DEPRECATED_MEMBER url; #endif private: - aux::allocation_slot const m_url_idx; + aux::allocation_slot m_url_idx; }; #define TORRENT_DEFINE_ALERT_IMPL(name, seq, prio) \ - name(name&&) = default; \ + name(name&&) noexcept = default; \ static const int priority = prio; \ static const int alert_type = seq; \ virtual int type() const override { return alert_type; } \ @@ -200,7 +201,7 @@ namespace libtorrent { TORRENT_DEFINE_ALERT_PRIO(torrent_removed_alert, 4) static const int static_category = alert::status_notification; virtual std::string message() const override; - sha1_hash const info_hash; + sha1_hash info_hash; }; // This alert is posted when the asynchronous read operation initiated by @@ -272,7 +273,7 @@ namespace libtorrent { // refers to the index of the file that was renamed, file_index_t const index; private: - aux::allocation_slot const m_name_idx; + aux::allocation_slot m_name_idx; }; // This is posted as a response to a torrent_handle::rename_file() call, if the rename @@ -446,7 +447,7 @@ namespace libtorrent { char const* error_message() const; private: - aux::allocation_slot const m_msg_idx; + aux::allocation_slot m_msg_idx; }; // This alert is triggered if the tracker reply contains a warning field. @@ -472,7 +473,7 @@ namespace libtorrent { char const* warning_message() const; private: - aux::allocation_slot const m_msg_idx; + aux::allocation_slot m_msg_idx; }; // This alert is generated when a scrape request succeeds. @@ -523,7 +524,7 @@ namespace libtorrent { char const* error_message() const; private: - aux::allocation_slot const m_msg_idx; + aux::allocation_slot m_msg_idx; }; // This alert is only for informational purpose. It is generated when a tracker announce @@ -891,7 +892,7 @@ namespace libtorrent { char const* storage_path() const; private: - aux::allocation_slot const m_path_idx; + aux::allocation_slot m_path_idx; }; // The ``storage_moved_failed_alert`` is generated when an attempt to move the storage, @@ -922,7 +923,7 @@ namespace libtorrent { // terminated string naming which one, otherwise it's nullptr. char const* operation; private: - aux::allocation_slot const m_file_idx; + aux::allocation_slot m_file_idx; }; // This alert is generated when a request to delete the files of a torrent complete. @@ -945,7 +946,7 @@ namespace libtorrent { static const int static_category = alert::storage_notification; virtual std::string message() const override; - sha1_hash const info_hash; + sha1_hash info_hash; }; // This alert is generated when a request to delete the files of a torrent fails. @@ -966,7 +967,7 @@ namespace libtorrent { error_code const error; // the info hash of the torrent whose files failed to be deleted - sha1_hash const info_hash; + sha1_hash info_hash; #ifndef TORRENT_NO_DEPRECATE std::string TORRENT_DEPRECATED_MEMBER msg; @@ -1094,8 +1095,8 @@ namespace libtorrent { char const* error_message() const; private: - aux::allocation_slot const m_url_idx; - aux::allocation_slot const m_msg_idx; + aux::allocation_slot m_url_idx; + aux::allocation_slot m_msg_idx; }; // If the storage fails to read or write files that it needs access to, this alert is @@ -1129,7 +1130,7 @@ namespace libtorrent { std::string TORRENT_DEPRECATED_MEMBER msg; #endif private: - aux::allocation_slot const m_file_idx; + aux::allocation_slot m_file_idx; }; // This alert is generated when the metadata has been completely received and the info-hash @@ -1205,7 +1206,7 @@ namespace libtorrent { virtual std::string message() const override; // the source address associated with the error (if any) - udp::endpoint const endpoint; + aux::noexcept_movable endpoint; // the error code describing the error error_code const error; @@ -1226,7 +1227,7 @@ namespace libtorrent { virtual std::string message() const override; // the IP address that is believed to be our external IP - address const external_address; + aux::noexcept_movable
external_address; }; enum class socket_type_t : std::uint8_t @@ -1295,7 +1296,7 @@ namespace libtorrent { // the address libtorrent attempted to listen on // see alert's documentation for validity of this value - libtorrent::address const address; + aux::noexcept_movable address; // the port libtorrent attempted to listen on // see alert's documentation for validity of this value @@ -1303,7 +1304,7 @@ namespace libtorrent { #ifndef TORRENT_NO_DEPRECATE // the address and port libtorrent attempted to listen on - tcp::endpoint endpoint; + aux::noexcept_movable endpoint; // the type of listen socket this alert refers to. socket_type_t sock_type; @@ -1311,7 +1312,7 @@ namespace libtorrent { private: std::reference_wrapper m_alloc; - aux::allocation_slot const m_interface_idx; + aux::allocation_slot m_interface_idx; }; // This alert is posted when the listen port succeeds to be opened on a @@ -1344,7 +1345,7 @@ namespace libtorrent { // the address libtorrent ended up listening on. This address // refers to the local interface. - libtorrent::address const address; + aux::noexcept_movable address; // the port libtorrent ended up listening on. int const port; @@ -1355,7 +1356,7 @@ namespace libtorrent { #ifndef TORRENT_NO_DEPRECATE // the endpoint libtorrent ended up listening on. The address // refers to the local interface and the port is the listen port. - tcp::endpoint endpoint; + aux::noexcept_movable endpoint; // the type of listen socket this alert refers to. socket_type_t sock_type; @@ -1458,7 +1459,7 @@ namespace libtorrent { // TODO: 2 should the alert baseclass have this object instead? std::reference_wrapper m_alloc; - aux::allocation_slot const m_log_idx; + aux::allocation_slot m_log_idx; }; // This alert is generated when a fastresume file has been passed to @@ -1477,7 +1478,7 @@ namespace libtorrent { | alert::error_notification; virtual std::string message() const override; - error_code const error; + error_code error; #ifndef TORRENT_NO_DEPRECATE // If the error happened to a specific file, ``file`` is the path to it. @@ -1495,7 +1496,7 @@ namespace libtorrent { std::string TORRENT_DEPRECATED_MEMBER msg; #endif private: - aux::allocation_slot const m_path_idx; + aux::allocation_slot m_path_idx; }; // This alert is posted when an incoming peer connection, or a peer that's about to be added @@ -1546,9 +1547,9 @@ namespace libtorrent { static const int static_category = alert::dht_notification; virtual std::string message() const override; - address const ip; - int const port; - sha1_hash const info_hash; + aux::noexcept_movable
ip; + int port; + sha1_hash info_hash; }; // This alert is generated when a DHT node sends a ``get_peers`` message to @@ -1563,7 +1564,7 @@ namespace libtorrent { static const int static_category = alert::dht_notification; virtual std::string message() const override; - sha1_hash const info_hash; + sha1_hash info_hash; }; // This alert is posted approximately once every second, and it contains @@ -1657,8 +1658,8 @@ namespace libtorrent { }; // specifies what error this is, see kind_t. - int const kind; - std::string const str; + int kind; + std::string str; }; // This alert is generated when we receive a local service discovery message @@ -1698,7 +1699,7 @@ namespace libtorrent { char const* tracker_id() const; private: - aux::allocation_slot const m_tracker_idx; + aux::allocation_slot m_tracker_idx; }; // This alert is posted when the initial DHT bootstrap is done. @@ -1737,7 +1738,7 @@ namespace libtorrent { char const* filename() const; private: - aux::allocation_slot const m_file_idx; + aux::allocation_slot m_file_idx; }; // This is always posted for SSL torrents. This is a reminder to the client that @@ -1792,11 +1793,11 @@ namespace libtorrent { int const socket_type; // is the IP address and port the connection came from. - tcp::endpoint const endpoint; + aux::noexcept_movable endpoint; #ifndef TORRENT_NO_DEPRECATE // is the IP address and port the connection came from. - tcp::endpoint const ip; + aux::noexcept_movable TORRENT_DEPRECATED_MEMBER ip; #endif }; @@ -1817,10 +1818,10 @@ namespace libtorrent { // a copy of the parameters used when adding the torrent, it can be used // to identify which invocation to ``async_add_torrent()`` caused this alert. - add_torrent_params const params; + add_torrent_params params; // set to the error, if one occurred while adding the torrent. - error_code const error; + error_code error; }; // This alert is only posted when requested by the user, by calling @@ -1843,7 +1844,7 @@ namespace libtorrent { // to a specific torrent via its ``handle`` member. The receiving end is // suggested to have all torrents sorted by the torrent_handle or hashed // by it, for efficient updates. - std::vector const status; + std::vector status; }; #ifndef TORRENT_NO_DEPRECATE @@ -1943,7 +1944,7 @@ namespace libtorrent { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif - struct TORRENT_DEPRECATED TORRENT_EXPORT torrent_update_alert final : torrent_alert + struct TORRENT_DEPRECATED_EXPORT torrent_update_alert final : torrent_alert { // internal torrent_update_alert(aux::stack_allocator& alloc, torrent_handle h @@ -1979,7 +1980,7 @@ namespace libtorrent { virtual std::string message() const override; // the error code - error_code const error; + error_code error; enum op_t { @@ -2006,10 +2007,10 @@ namespace libtorrent { // the target hash of the immutable item. This must // match the sha-1 hash of the bencoded form of ``item``. - sha1_hash const target; + sha1_hash target; // the data for this item - entry const item; + entry item; }; // this alert is posted as a response to a call to session::get_item(), @@ -2026,27 +2027,27 @@ namespace libtorrent { virtual std::string message() const override; // the public key that was looked up - std::array const key; + std::array key; // the signature of the data. This is not the signature of the // plain encoded form of the item, but it includes the sequence number // and possibly the hash as well. See the dht_store document for more // information. This is primarily useful for echoing back in a store // request. - std::array const signature; + std::array signature; // the sequence number of this item - std::int64_t const seq; + std::int64_t seq; // the salt, if any, used to lookup and store this item. If no // salt was used, this is an empty string - std::string const salt; + std::string salt; // the data for this item - entry const item; + entry item; // the last response for mutable data is authoritative. - bool const authoritative; + bool authoritative; }; // this is posted when a DHT put operation completes. This is useful if the @@ -2068,20 +2069,20 @@ namespace libtorrent { // the target hash the item was stored under if this was an *immutable* // item. - sha1_hash const target; + sha1_hash target; // if a mutable item was stored, these are the public key, signature, // salt and sequence number the item was stored under. - std::array const public_key; - std::array const signature; - std::string const salt; - std::int64_t const seq; + std::array public_key; + std::array signature; + std::string salt; + std::int64_t seq; // DHT put operation usually writes item to k nodes, maybe the node // is stale so no response, or the node doesn't support 'put', or the // token for write is out of date, etc. num_success is the number of // successful responses we got from the puts. - int const num_success; + int num_success; }; // this alert is used to report errors in the i2p SAM connection @@ -2095,7 +2096,7 @@ namespace libtorrent { virtual std::string message() const override; // the error that occurred in the i2p SAM connection - error_code const error; + error_code error; }; // This alert is generated when we send a get_peers request @@ -2113,18 +2114,18 @@ namespace libtorrent { virtual std::string message() const override; // the info_hash of the torrent we're looking for peers for. - sha1_hash const info_hash; + sha1_hash info_hash; // if this was an obfuscated lookup, this is the info-hash target // actually sent to the node. - sha1_hash const obfuscated_info_hash; + sha1_hash obfuscated_info_hash; // the endpoint we're sending this query to - udp::endpoint const endpoint; + aux::noexcept_movable endpoint; #ifndef TORRENT_NO_DEPRECATE // the endpoint we're sending this query to - udp::endpoint ip; + aux::noexcept_movable TORRENT_DEPRECATED_MEMBER ip; #endif }; @@ -2154,7 +2155,7 @@ namespace libtorrent { private: std::reference_wrapper m_alloc; - aux::allocation_slot const m_str_idx; + aux::allocation_slot m_str_idx; }; // This alert is posted by torrent wide events. It's meant to be used for @@ -2182,7 +2183,7 @@ namespace libtorrent { #endif private: - aux::allocation_slot const m_str_idx; + aux::allocation_slot m_str_idx; }; // This alert is posted by events specific to a peer. It's meant to be used @@ -2217,7 +2218,7 @@ namespace libtorrent { // message name. char const* event_type; - direction_t const direction; + direction_t direction; // returns the log message char const* log_message() const; @@ -2229,7 +2230,7 @@ namespace libtorrent { #endif private: - aux::allocation_slot const m_str_idx; + aux::allocation_slot m_str_idx; }; // posted if the local service discovery socket fails to start properly. @@ -2245,7 +2246,7 @@ namespace libtorrent { virtual std::string message() const override; // The error code - error_code const error; + error_code error; }; // holds statistics about a current dht_lookup operation. @@ -2322,11 +2323,11 @@ namespace libtorrent { virtual std::string message() const override; // a vector of the currently running DHT lookups. - std::vector const active_requests; + std::vector active_requests; // contains information about every bucket in the DHT routing // table. - std::vector const routing_table; + std::vector routing_table; }; // posted every time an incoming request from a peer is accepted and queued @@ -2346,7 +2347,7 @@ namespace libtorrent { virtual std::string message() const override; // the request this peer sent to us - peer_request const req; + peer_request req; }; struct TORRENT_EXPORT dht_log_alert final : alert @@ -2372,11 +2373,11 @@ namespace libtorrent { char const* log_message() const; // the module, or part, of the DHT that produced this log message. - dht_module_t const module; + dht_module_t module; private: std::reference_wrapper m_alloc; - aux::allocation_slot const m_msg_idx; + aux::allocation_slot m_msg_idx; }; // This alert is posted every time a DHT message is sent or received. It is @@ -2402,19 +2403,19 @@ namespace libtorrent { span pkt_buf() const; // whether this is an incoming or outgoing packet. - direction_t const direction; + direction_t direction; // the DHT node we received this packet from, or sent this packet to // (depending on ``direction``). - udp::endpoint const node; + aux::noexcept_movable node; #ifndef TORRENT_NO_DEPRECATE - direction_t const dir; + direction_t TORRENT_DEPRECATED_MEMBER dir; #endif private: std::reference_wrapper m_alloc; - aux::allocation_slot const m_msg_idx; + aux::allocation_slot m_msg_idx; int const m_size; }; @@ -2429,7 +2430,7 @@ namespace libtorrent { virtual std::string message() const override; - sha1_hash const info_hash; + sha1_hash info_hash; int num_peers() const; @@ -2464,17 +2465,17 @@ namespace libtorrent { virtual std::string message() const override; void const* userdata; - udp::endpoint const endpoint; + aux::noexcept_movable endpoint; bdecode_node response() const; #ifndef TORRENT_NO_DEPRECATE - udp::endpoint const addr; + aux::noexcept_movable TORRENT_DEPRECATED_MEMBER addr; #endif private: std::reference_wrapper m_alloc; - aux::allocation_slot const m_response_idx; + aux::allocation_slot m_response_idx; int const m_response_size; }; @@ -2522,7 +2523,7 @@ namespace libtorrent { std::vector blocks() const; private: - aux::allocation_slot const m_array_idx; + aux::allocation_slot m_array_idx; int const m_num_blocks; }; @@ -2544,7 +2545,7 @@ namespace libtorrent { private: std::reference_wrapper m_alloc; - aux::allocation_slot const m_msg_idx; + aux::allocation_slot m_msg_idx; }; struct TORRENT_EXPORT dht_live_nodes_alert final : alert @@ -2558,7 +2559,7 @@ namespace libtorrent { static const int static_category = alert::dht_notification; virtual std::string message() const override; - sha1_hash const node_id; + sha1_hash node_id; int num_nodes() const; std::vector> nodes() const; diff --git a/include/libtorrent/aux_/noexcept_movable.hpp b/include/libtorrent/aux_/noexcept_movable.hpp new file mode 100644 index 000000000..28715ebde --- /dev/null +++ b/include/libtorrent/aux_/noexcept_movable.hpp @@ -0,0 +1,72 @@ +/* + +Copyright (c) 2017, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ +#ifndef TORRENT_NOEXCEPT_MOVABLE_HPP_INCLUDED +#define TORRENT_NOEXCEPT_MOVABLE_HPP_INCLUDED + +namespace libtorrent { +namespace aux { + + // this is a silly wrapper for address and endpoint to make their move + // constructors be noexcept (because boost.asio is incorrectly making them + // potentially throwing). This can be removed once libtorrent uses the + // networking TS. + template + struct noexcept_movable : T + { + noexcept_movable() noexcept {} + noexcept_movable(noexcept_movable&& rhs) noexcept + : T(std::forward(rhs)) + {} + noexcept_movable(noexcept_movable const& rhs) + : T(static_cast(rhs)) + {} + noexcept_movable(T&& rhs) noexcept : T(std::forward(rhs)) {} // NOLINT + noexcept_movable(T const& rhs) : T(rhs) {} // NOLINT + noexcept_movable& operator=(noexcept_movable&& rhs) noexcept + { + this->T::operator=(std::forward(rhs)); + return *this; + } + noexcept_movable& operator=(noexcept_movable const& rhs) + { + this->T::operator=(rhs); + return *this; + } + + using T::T; + using T::operator=; + }; + +} +} + +#endif diff --git a/include/libtorrent/aux_/scope_end.hpp b/include/libtorrent/aux_/scope_end.hpp index 11d7acbd6..4162d94d9 100644 --- a/include/libtorrent/aux_/scope_end.hpp +++ b/include/libtorrent/aux_/scope_end.hpp @@ -44,8 +44,8 @@ namespace libtorrent { namespace aux { ~scope_end_impl() { if (m_armed) m_fun(); } // movable - scope_end_impl(scope_end_impl&&) = default; - scope_end_impl& operator=(scope_end_impl&&) = default; + scope_end_impl(scope_end_impl&&) noexcept = default; + scope_end_impl& operator=(scope_end_impl&&) noexcept = default; // non-copyable scope_end_impl(scope_end_impl const&) = delete; diff --git a/include/libtorrent/aux_/vector.hpp b/include/libtorrent/aux_/vector.hpp index ae0c0877b..1c8a7641b 100644 --- a/include/libtorrent/aux_/vector.hpp +++ b/include/libtorrent/aux_/vector.hpp @@ -50,6 +50,15 @@ namespace libtorrent { namespace aux { // pull in constructors from base class using base::base; + vector() noexcept {} + vector(vector const&) = default; + vector& operator=(vector const&) = default; + + // the move constructor of std::vector isn't noexcept until C++17 + vector(vector&& rhs) noexcept : base(std::forward(rhs)) {} + vector& operator=(vector&& rhs) noexcept + { this->base::operator=(std::forward(rhs)); return *this; } + auto operator[](IndexType idx) const -> #if TORRENT_AUTO_RETURN_TYPES decltype(auto) diff --git a/include/libtorrent/bdecode.hpp b/include/libtorrent/bdecode.hpp index 9a1b5b66c..6b409b1a5 100644 --- a/include/libtorrent/bdecode.hpp +++ b/include/libtorrent/bdecode.hpp @@ -262,8 +262,8 @@ struct TORRENT_EXPORT bdecode_node // underlying buffer remains the same. bdecode_node(bdecode_node const&); bdecode_node& operator=(bdecode_node const&); - bdecode_node(bdecode_node&&); - bdecode_node& operator=(bdecode_node&&); + bdecode_node(bdecode_node&&) noexcept; + bdecode_node& operator=(bdecode_node&&) noexcept; // the types of bdecoded nodes enum type_t diff --git a/include/libtorrent/bitfield.hpp b/include/libtorrent/bitfield.hpp index 59e28c02f..b95b41d49 100644 --- a/include/libtorrent/bitfield.hpp +++ b/include/libtorrent/bitfield.hpp @@ -56,12 +56,12 @@ namespace libtorrent { // The constructor taking a pointer ``b`` and ``bits`` copies a bitfield // from the specified buffer, and ``bits`` number of bits (rounded up to // the nearest byte boundary). - bitfield() = default; + bitfield() noexcept = default; explicit bitfield(int bits) { resize(bits); } bitfield(int bits, bool val) { resize(bits, val); } bitfield(char const* b, int bits) { assign(b, bits); } bitfield(bitfield const& rhs) { assign(rhs.data(), rhs.size()); } - bitfield(bitfield&& rhs) = default; + bitfield(bitfield&& rhs) noexcept = default; // copy bitfield from buffer ``b`` of ``bits`` number of bits, rounded up to // the nearest byte boundary. @@ -146,7 +146,7 @@ namespace libtorrent { return *this; } - bitfield& operator=(bitfield&& rhs) = default; + bitfield& operator=(bitfield&& rhs) noexcept = default; void swap(bitfield& rhs) { @@ -256,9 +256,35 @@ namespace libtorrent { aux::unique_ptr m_buf; }; + static_assert(std::is_nothrow_move_constructible::value + , "should be nothrow move constructible"); + static_assert(std::is_nothrow_move_assignable::value + , "should be nothrow move assignable"); + static_assert(std::is_nothrow_default_constructible::value + , "should be nothrow default constructible"); + template struct typed_bitfield : bitfield { + typed_bitfield() noexcept {} + typed_bitfield(typed_bitfield&& rhs) noexcept + : bitfield(std::forward(rhs)) + {} + typed_bitfield(typed_bitfield const& rhs) + : bitfield(static_cast(rhs)) + {} + typed_bitfield(bitfield&& rhs) noexcept : bitfield(std::forward(rhs)) {} // NOLINT + typed_bitfield(bitfield const& rhs) : bitfield(rhs) {} // NOLINT + typed_bitfield& operator=(typed_bitfield&& rhs) noexcept + { + this->bitfield::operator=(std::forward(rhs)); + return *this; + } + typed_bitfield& operator=(typed_bitfield const& rhs) + { + this->bitfield::operator=(rhs); + return *this; + } using bitfield::bitfield; bool operator[](IndexType const index) const @@ -276,6 +302,13 @@ namespace libtorrent { IndexType end_index() const { return IndexType(this->size()); } }; + static_assert(std::is_nothrow_move_constructible>::value + , "should be nothrow move constructible"); + static_assert(std::is_nothrow_move_assignable>::value + , "should be nothrow move assignable"); + static_assert(std::is_nothrow_default_constructible>::value + , "should be nothrow default constructible"); + } #endif // TORRENT_BITFIELD_HPP_INCLUDED diff --git a/include/libtorrent/block_cache.hpp b/include/libtorrent/block_cache.hpp index 4c775056b..203e1a744 100644 --- a/include/libtorrent/block_cache.hpp +++ b/include/libtorrent/block_cache.hpp @@ -166,8 +166,8 @@ namespace aux { { cached_piece_entry(); ~cached_piece_entry(); - cached_piece_entry(cached_piece_entry&&) = default; - cached_piece_entry& operator=(cached_piece_entry&&) = default; + cached_piece_entry(cached_piece_entry&&) noexcept = default; + cached_piece_entry& operator=(cached_piece_entry&&) noexcept = default; bool ok_to_evict(bool ignore_hash = false) const { diff --git a/include/libtorrent/disk_interface.hpp b/include/libtorrent/disk_interface.hpp index 6dc1394c8..5059d0c79 100644 --- a/include/libtorrent/disk_interface.hpp +++ b/include/libtorrent/disk_interface.hpp @@ -212,14 +212,14 @@ namespace libtorrent { storage_holder(storage_holder const&) = delete; storage_holder& operator=(storage_holder const&) = delete; - storage_holder(storage_holder&& rhs) + storage_holder(storage_holder&& rhs) noexcept : m_disk_io(rhs.m_disk_io) , m_idx(rhs.m_idx) { rhs.m_disk_io = nullptr; } - storage_holder& operator=(storage_holder&& rhs) + storage_holder& operator=(storage_holder&& rhs) noexcept { if (m_disk_io) m_disk_io->remove_torrent(m_idx); m_disk_io = rhs.m_disk_io; diff --git a/include/libtorrent/entry.hpp b/include/libtorrent/entry.hpp index 6c4ffef40..a0b45b424 100644 --- a/include/libtorrent/entry.hpp +++ b/include/libtorrent/entry.hpp @@ -176,7 +176,7 @@ namespace aux { // hidden entry(entry const& e); - entry(entry&& e); + entry(entry&& e) noexcept; // hidden entry(); @@ -195,7 +195,7 @@ namespace aux { #endif entry& operator=(bdecode_node const&); entry& operator=(entry const&); - entry& operator=(entry&&); + entry& operator=(entry&&) noexcept; entry& operator=(dictionary_type); entry& operator=(span); template ::const_iterator iterator; - typedef std::vector::const_reverse_iterator reverse_iterator; + using iterator = std::vector::const_iterator; + using reverse_iterator = std::vector::const_reverse_iterator; TORRENT_DEPRECATED iterator file_at_offset(std::int64_t offset) const; @@ -405,7 +408,7 @@ namespace libtorrent { std::string const& name() const { return m_name; } // swap all content of *this* with *ti*. - void swap(file_storage& ti) + void swap(file_storage& ti) noexcept { using std::swap; swap(ti.m_files, m_files); @@ -598,7 +601,7 @@ namespace libtorrent { // name of torrent. For multi-file torrents // this is always the root directory - std::string m_name; + aux::noexcept_movable m_name; // the sum of all file sizes std::int64_t m_total_size; diff --git a/include/libtorrent/heterogeneous_queue.hpp b/include/libtorrent/heterogeneous_queue.hpp index 63b0a20ee..63d255eff 100644 --- a/include/libtorrent/heterogeneous_queue.hpp +++ b/include/libtorrent/heterogeneous_queue.hpp @@ -221,9 +221,7 @@ namespace libtorrent { dst += sizeof(header_t) + src_hdr->pad_bytes; int const len = src_hdr->len; TORRENT_ASSERT(src + len <= end); - // TODO: if this throws, we should technically destruct the elements - // we've constructed so far, but maybe we should just disallow - // throwing move instead. + // this is no-throw src_hdr->move(dst, src); src_hdr->~header_t(); src += len ; @@ -235,8 +233,12 @@ namespace libtorrent { } template - static void move(char* dst, char* src) + static void move(char* dst, char* src) noexcept { + static_assert(std::is_nothrow_move_constructible::value + , "heterogeneous queue only supports noexcept move constructible types"); + static_assert(std::is_nothrow_destructible::value + , "heterogeneous queue only supports noexcept destructible types"); U& rhs = *reinterpret_cast(src); TORRENT_ASSERT((reinterpret_cast(dst) & (alignof(U) - 1)) == 0); diff --git a/include/libtorrent/netlink.hpp b/include/libtorrent/netlink.hpp index 9e26622d8..46c52c73b 100644 --- a/include/libtorrent/netlink.hpp +++ b/include/libtorrent/netlink.hpp @@ -55,7 +55,7 @@ namespace libtorrent { using protocol_type = Protocol; using data_type = boost::asio::detail::socket_addr_type; - basic_nl_endpoint() : basic_nl_endpoint(protocol_type(), 0, 0) {} + basic_nl_endpoint() noexcept : basic_nl_endpoint(protocol_type(), 0, 0) {} basic_nl_endpoint(protocol_type netlink_family, std::uint32_t group, std::uint32_t pid = 0) : m_proto(netlink_family) @@ -66,18 +66,16 @@ namespace libtorrent { m_sockaddr.nl_pid = pid; } - basic_nl_endpoint(basic_nl_endpoint const& other) - { - m_sockaddr = other.m_sockaddr; - } + basic_nl_endpoint(basic_nl_endpoint const& other) = default; + basic_nl_endpoint(basic_nl_endpoint&& other) noexcept = default; - basic_nl_endpoint& operator=(const basic_nl_endpoint& other) + basic_nl_endpoint& operator=(basic_nl_endpoint const& other) { m_sockaddr = other.m_sockaddr; return *this; } - basic_nl_endpoint& operator=(const basic_nl_endpoint&& other) + basic_nl_endpoint& operator=(basic_nl_endpoint&& other) noexcept { m_sockaddr = other.m_sockaddr; return *this; diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index 2528931c1..46a357935 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -117,6 +117,8 @@ namespace aux { ~session_proxy(); session_proxy(session_proxy const&); session_proxy& operator=(session_proxy const&); + session_proxy(session_proxy&&) noexcept; + session_proxy& operator=(session_proxy&&) noexcept; private: session_proxy( std::shared_ptr ios diff --git a/include/libtorrent/session_handle.hpp b/include/libtorrent/session_handle.hpp index 925e4692f..75727b56c 100644 --- a/include/libtorrent/session_handle.hpp +++ b/include/libtorrent/session_handle.hpp @@ -75,9 +75,9 @@ namespace libtorrent { session_handle() {} session_handle(session_handle const& t) = default; - session_handle(session_handle&& t) = default; + session_handle(session_handle&& t) noexcept = default; session_handle& operator=(session_handle const&) = default; - session_handle& operator=(session_handle&&) = default; + session_handle& operator=(session_handle&&) noexcept = default; bool is_valid() const { return !m_impl.expired(); } diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 0cf126326..9c43c1658 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -86,9 +86,9 @@ namespace libtorrent { settings_pack() = default; settings_pack(settings_pack const&) = default; - settings_pack(settings_pack&&) = default; + settings_pack(settings_pack&&) noexcept = default; settings_pack& operator=(settings_pack const&) = default; - settings_pack& operator=(settings_pack&&) = default; + settings_pack& operator=(settings_pack&&) noexcept = default; void set_str(int name, std::string val); void set_int(int name, int val); diff --git a/include/libtorrent/sha1_hash.hpp b/include/libtorrent/sha1_hash.hpp index 214d1c08b..c4adfa61f 100644 --- a/include/libtorrent/sha1_hash.hpp +++ b/include/libtorrent/sha1_hash.hpp @@ -74,12 +74,10 @@ namespace aux { static constexpr std::size_t size() { return N / 8; } // constructs an all-zero digest - digest32() { clear(); } + digest32() noexcept { clear(); } - digest32(digest32 const&) = default; - digest32(digest32&&) = default; - digest32& operator=(digest32 const&) = default; - digest32& operator=(digest32&&) = default; + digest32(digest32 const&) noexcept = default; + digest32& operator=(digest32 const&) noexcept = default; // returns an all-F digest. i.e. the maximum value // representable by an N bit number (N/8 bytes). This is @@ -132,7 +130,7 @@ namespace aux { char* data() { return reinterpret_cast(&m_number[0]); } // set the digest to all zeroes. - void clear() { std::memset(m_number, 0, size()); } + void clear() noexcept { std::memset(m_number, 0, size()); } // return true if the digest is all zero. bool is_all_zeros() const @@ -278,6 +276,13 @@ namespace aux { // peer IDs, node IDs etc. using sha1_hash = digest32<160>; + static_assert(std::is_nothrow_move_constructible::value + , "should be nothrow move constructible"); + static_assert(std::is_nothrow_move_assignable::value + , "should be nothrow move assignable"); + static_assert(std::is_nothrow_default_constructible::value + , "should be nothrow default constructible"); + #if TORRENT_USE_IOSTREAM // print a sha1_hash object to an ostream as 40 hexadecimal digits diff --git a/include/libtorrent/stack_allocator.hpp b/include/libtorrent/stack_allocator.hpp index d7cf2159e..3c8252e34 100644 --- a/include/libtorrent/stack_allocator.hpp +++ b/include/libtorrent/stack_allocator.hpp @@ -46,16 +46,16 @@ namespace libtorrent { namespace aux { struct allocation_slot { - allocation_slot() : m_idx(-1) {} - allocation_slot(allocation_slot const&) = default; - allocation_slot(allocation_slot&&) = default; + allocation_slot() noexcept : m_idx(-1) {} + allocation_slot(allocation_slot const&) noexcept = default; + allocation_slot(allocation_slot&&) noexcept = default; allocation_slot& operator=(allocation_slot const&) = default; - allocation_slot& operator=(allocation_slot&&) = default; + allocation_slot& operator=(allocation_slot&&) noexcept = default; bool operator==(allocation_slot const& s) const { return m_idx == s.m_idx; } bool operator!=(allocation_slot const& s) const { return m_idx != s.m_idx; } friend struct stack_allocator; private: - explicit allocation_slot(int idx) : m_idx(idx) {} + explicit allocation_slot(int idx) noexcept : m_idx(idx) {} int val() const { return m_idx; } int m_idx; }; diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index adaf986f0..57091fb54 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -186,7 +186,7 @@ namespace libtorrent { #if defined __GNUC__ && defined _GLIBCXX_DEBUG // this works around a bug in libstdc++'s checked iterators // http://stackoverflow.com/questions/22915325/avoiding-self-assignment-in-stdshuffle - web_seed_t& operator=(web_seed_t&& rhs) + web_seed_t& operator=(web_seed_t&& rhs) noexcept { if (&rhs == this) return *this; diff --git a/include/libtorrent/torrent_handle.hpp b/include/libtorrent/torrent_handle.hpp index 5caaa4d69..b03c24bd9 100644 --- a/include/libtorrent/torrent_handle.hpp +++ b/include/libtorrent/torrent_handle.hpp @@ -155,10 +155,10 @@ namespace libtorrent { namespace aux { #ifndef TORRENT_NO_DEPRECATE #include "libtorrent/aux_/disable_warnings_push.hpp" partial_piece_info() = default; - partial_piece_info(partial_piece_info&&) = default; + partial_piece_info(partial_piece_info&&) noexcept = default; partial_piece_info(partial_piece_info const&) = default; partial_piece_info& operator=(partial_piece_info const&) = default; - partial_piece_info& operator=(partial_piece_info&&) = default; + partial_piece_info& operator=(partial_piece_info&&) noexcept = default; #include "libtorrent/aux_/disable_warnings_pop.hpp" #endif // the index of the piece in question. ``blocks_in_piece`` is the number @@ -258,12 +258,12 @@ namespace libtorrent { namespace aux { // constructs a torrent handle that does not refer to a torrent. // i.e. is_valid() will return false. - torrent_handle() {} + torrent_handle() noexcept {} torrent_handle(torrent_handle const& t) = default; - torrent_handle(torrent_handle&& t) = default; + torrent_handle(torrent_handle&& t) noexcept = default; torrent_handle& operator=(torrent_handle const&) = default; - torrent_handle& operator=(torrent_handle&&) = default; + torrent_handle& operator=(torrent_handle&&) noexcept = default; // flags for add_piece(). enum flags_t { overwrite_existing = 1 }; @@ -1311,9 +1311,14 @@ namespace libtorrent { namespace aux { { if (!t.expired()) m_torrent = t; } std::weak_ptr m_torrent; - }; + static_assert(std::is_nothrow_move_constructible::value + , "should be nothrow move constructible"); + static_assert(std::is_nothrow_move_assignable::value + , "should be nothrow move assignable"); + static_assert(std::is_nothrow_default_constructible::value + , "should be nothrow default constructible"); } namespace std diff --git a/include/libtorrent/torrent_status.hpp b/include/libtorrent/torrent_status.hpp index 45d81d2c2..66cd3e5cf 100644 --- a/include/libtorrent/torrent_status.hpp +++ b/include/libtorrent/torrent_status.hpp @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/time.hpp" // for time_duration #include "libtorrent/storage_defs.hpp" // for storage_mode_t #include "libtorrent/error_code.hpp" +#include "libtorrent/aux_/noexcept_movable.hpp" #include #include @@ -52,11 +53,13 @@ namespace libtorrent { struct TORRENT_EXPORT torrent_status { // hidden - torrent_status(); + torrent_status() noexcept; ~torrent_status(); torrent_status(torrent_status const&); torrent_status& operator=(torrent_status const&); - torrent_status(torrent_status&&); + torrent_status(torrent_status&&) noexcept; + // TODO: 2 msvc and GCC did not make std::string nothrow move-assignable + // until C++17 torrent_status& operator=(torrent_status&&); // compares if the torrent status objects come from the same torrent. i.e. @@ -557,6 +560,13 @@ namespace libtorrent { seconds finished_duration; seconds seeding_duration; }; + + static_assert(std::is_nothrow_move_constructible::value + , "should be nothrow move constructible"); +// static_assert(std::is_nothrow_move_assignable::value +// , "should be nothrow move assignable"); + static_assert(std::is_nothrow_default_constructible::value + , "should be nothrow default constructible"); } namespace std diff --git a/include/libtorrent/units.hpp b/include/libtorrent/units.hpp index eacca0fa4..5e94fc866 100644 --- a/include/libtorrent/units.hpp +++ b/include/libtorrent/units.hpp @@ -52,8 +52,9 @@ namespace libtorrent { namespace aux { using underlying_type = UnderlyingType; using diff_type = strong_typedef>; - constexpr strong_typedef(strong_typedef const& rhs) : m_val(rhs.m_val) {} - strong_typedef() = default; + constexpr strong_typedef(strong_typedef const& rhs) noexcept = default; + constexpr strong_typedef(strong_typedef&& rhs) noexcept = default; + strong_typedef() noexcept = default; #ifndef TORRENT_NO_DEPRECATE constexpr strong_typedef(UnderlyingType val) : m_val(val) {} constexpr operator UnderlyingType() const { return m_val; } @@ -87,7 +88,8 @@ namespace libtorrent { namespace aux { strong_typedef& operator-=(diff_type rhs) { m_val -= static_cast(rhs); return *this; } - strong_typedef& operator=(strong_typedef rhs) { m_val = rhs.m_val; return *this; } + strong_typedef& operator=(strong_typedef const& rhs) noexcept = default; + strong_typedef& operator=(strong_typedef&& rhs) noexcept = default; private: UnderlyingType m_val; }; diff --git a/include/libtorrent/utp_stream.hpp b/include/libtorrent/utp_stream.hpp index 413dc6996..3326457d3 100644 --- a/include/libtorrent/utp_stream.hpp +++ b/include/libtorrent/utp_stream.hpp @@ -191,8 +191,8 @@ struct TORRENT_EXTRA_EXPORT utp_stream ~utp_stream(); utp_stream& operator=(utp_stream const&) = delete; utp_stream(utp_stream const&) = delete; - utp_stream& operator=(utp_stream&&) = default; - utp_stream(utp_stream&&) = default; + utp_stream& operator=(utp_stream&&) noexcept = default; + utp_stream(utp_stream&&) noexcept = default; lowest_layer_type& lowest_layer() { return *this; } diff --git a/src/bdecode.cpp b/src/bdecode.cpp index d93a7e926..4a729fc12 100644 --- a/src/bdecode.cpp +++ b/src/bdecode.cpp @@ -244,8 +244,8 @@ namespace { return *this; } - bdecode_node::bdecode_node(bdecode_node&&) = default; - bdecode_node& bdecode_node::operator=(bdecode_node&&) = default; + bdecode_node::bdecode_node(bdecode_node&&) noexcept = default; + bdecode_node& bdecode_node::operator=(bdecode_node&&) noexcept = default; bdecode_node::bdecode_node(bdecode_token const* tokens, char const* buf , int len, int idx) diff --git a/src/entry.cpp b/src/entry.cpp index 784ad33fe..05bbb3e2f 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -132,7 +132,7 @@ namespace { return *this; } - entry& entry::operator=(entry&& e) + entry& entry::operator=(entry&& e) noexcept { swap(e); return *this; @@ -269,7 +269,7 @@ namespace { #endif } - entry::entry(entry&& e) + entry::entry(entry&& e) noexcept : m_type(undefined_t) { #if TORRENT_USE_ASSERTS @@ -572,7 +572,7 @@ namespace { #endif } - void entry::swap(entry& e) + void entry::swap(entry& e) noexcept { bool clear_this = false; bool clear_that = false; diff --git a/src/file_storage.cpp b/src/file_storage.cpp index fbecd416e..560e6f2f4 100644 --- a/src/file_storage.cpp +++ b/src/file_storage.cpp @@ -70,6 +70,8 @@ namespace libtorrent { // of libtorrent and properly exported by the .dll. file_storage::file_storage(file_storage const&) = default; file_storage& file_storage::operator=(file_storage const&) = default; + file_storage::file_storage(file_storage&&) noexcept = default; + file_storage& file_storage::operator=(file_storage&&) noexcept = default; void file_storage::reserve(int num_files) { @@ -242,7 +244,7 @@ namespace { return *this; } - internal_file_entry::internal_file_entry(internal_file_entry&& fe) + internal_file_entry::internal_file_entry(internal_file_entry&& fe) noexcept : offset(fe.offset) , symlink_index(fe.symlink_index) , no_root_dir(fe.no_root_dir) @@ -259,7 +261,7 @@ namespace { fe.name = nullptr; } - internal_file_entry& internal_file_entry::operator=(internal_file_entry&& fe) + internal_file_entry& internal_file_entry::operator=(internal_file_entry&& fe) noexcept { offset = fe.offset; size = fe.size; @@ -278,9 +280,6 @@ namespace { return *this; } - file_storage::file_storage(file_storage&&) = default; - file_storage& file_storage::operator=(file_storage&&) = default; - // if borrow_chars >= 0, don't take ownership over n, just // point to it. It points to borrow_chars number of characters. // if borrow_chars == -1, n is a 0-terminated string that diff --git a/src/session.cpp b/src/session.cpp index ebc841a3c..20f1276bf 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -404,6 +404,8 @@ namespace { {} session_proxy::session_proxy(session_proxy const&) = default; session_proxy& session_proxy::operator=(session_proxy const&) = default; + session_proxy::session_proxy(session_proxy&&) noexcept = default; + session_proxy& session_proxy::operator=(session_proxy&&) noexcept = default; session_proxy::~session_proxy() { if (m_thread && m_thread.unique()) diff --git a/src/torrent_status.cpp b/src/torrent_status.cpp index 44d1bd45c..6daf65e74 100644 --- a/src/torrent_status.cpp +++ b/src/torrent_status.cpp @@ -39,10 +39,10 @@ namespace libtorrent { file_index_t constexpr torrent_status::error_file_ssl_ctx; file_index_t constexpr torrent_status::error_file_metadata; file_index_t constexpr torrent_status::error_file_exception; - torrent_status::torrent_status() = default; + torrent_status::torrent_status() noexcept {} torrent_status::~torrent_status() = default; torrent_status::torrent_status(torrent_status const&) = default; torrent_status& torrent_status::operator=(torrent_status const&) = default; - torrent_status::torrent_status(torrent_status&&) = default; + torrent_status::torrent_status(torrent_status&&) noexcept = default; torrent_status& torrent_status::operator=(torrent_status&&) = default; } diff --git a/test/test_buffer.cpp b/test/test_buffer.cpp index 74e67083c..fde0bdbf5 100644 --- a/test/test_buffer.cpp +++ b/test/test_buffer.cpp @@ -186,8 +186,8 @@ struct holder ~holder() { if (m_buf) free_buffer(m_buf); } holder(holder const&) = delete; holder& operator=(holder const&) = delete; - holder(holder&& rhs) : m_buf(rhs.m_buf) { rhs.m_buf = nullptr; } - holder& operator=(holder&& rhs) + holder(holder&& rhs) noexcept : m_buf(rhs.m_buf) { rhs.m_buf = nullptr; } + holder& operator=(holder&& rhs) noexcept { if (m_buf) free_buffer(m_buf); m_buf = rhs.m_buf; diff --git a/test/test_heterogeneous_queue.cpp b/test/test_heterogeneous_queue.cpp index 7c8e25e01..a9ce36ff4 100644 --- a/test/test_heterogeneous_queue.cpp +++ b/test/test_heterogeneous_queue.cpp @@ -39,6 +39,7 @@ struct A { int a; explicit A(int a_) : a(a_) {} + A(A&&) noexcept = default; virtual int type() = 0; virtual ~A() = default; }; @@ -47,6 +48,7 @@ struct B : A { int b; explicit B(int a_, int b_) : A(a_), b(b_) {} + B(B&&) noexcept = default; int type() override { return 1; } }; @@ -57,6 +59,7 @@ struct C : A { memset(c, c_, sizeof(c)); } + C(C&&) noexcept = default; int type() override { return 2; } }; @@ -65,6 +68,7 @@ struct D static int instances; D() { ++instances; } D(D const& d) { ++instances; } + D(D&&) noexcept { ++instances; } ~D() { --instances; } }; @@ -72,6 +76,7 @@ struct D struct E { explicit E(char const* msg) : string_member(msg) {} + E(E&&) noexcept = default; std::string string_member; }; @@ -98,7 +103,7 @@ struct F TEST_EQUAL(f_.gutted, false); } - F(F&& f_) + F(F&& f_) noexcept : self(this) , f(f_.f) , constructed(f_.constructed) @@ -141,6 +146,7 @@ private: struct G : A { G(int base, int v) : A(base), g(v) {} + G(G&&) noexcept = default; int type() override { return 3; } std::int64_t g; };