Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/move if noexcept"

From cppreference.com
< cpp‎ | utility
m (Text replace - "{{example cpp" to "{{example")
m (Apply {{dcla}}'s "constexpr=" param.)
 
(21 intermediate revisions by 14 users not shown)
Line 1: Line 1:
 
{{cpp/title|move_if_noexcept}}
 
{{cpp/title|move_if_noexcept}}
{{cpp/utility/sidebar}}
+
{{cpp/utility/navbar}}
{{ddcl list begin}}
+
{{dcl begin}}
{{ddcl list header | utility}}
+
{{dcl header|utility}}
{{ddcl list item | notes={{mark since c++11}} |
+
{{dcla|since=c++11|constexpr=c++14|
 
template< class T >
 
template< class T >
typename std::conditional< 
+
/* see below */ move_if_noexcept( T& x ) noexcept;
    !std::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value,
+
    const T&,
+
    T&&
+
>::type move_if_noexcept(T& x);
+
 
}}
 
}}
{{ddcl list end}}
+
{{dcl end}}
  
Obtains an rvalue reference to its argument if its move constructor does not throw exceptions, otherwise obtains an lvalue reference to its argument. Typically used to combine move semantics with strong exception guarantee.
+
{{tt|std::move_if_noexcept}} obtains an rvalue reference to its argument if its move constructor does not throw exceptions or if there is no copy constructor (move-only type), otherwise obtains an lvalue reference to its argument. It is typically used to combine move semantics with strong exception guarantee.
  
For example, {{cpp|std::vector::resize()}} allocates new storage, and then moves or copies elements from old storage to new storage. If an exception occurs during this, {{cpp|std::vector::resize()}} undoes everything it did to this point, which is only possible if {{cpp|std::move_if_noexcept}} was used to decide whether to use move construction or copy construction.
+
The return type of {{tt|std::move_if_noexcept}} is:
 +
* {{c|T&&}} if {{c|std::is_nothrow_move_constructible<T>::value {{!!}} !std::is_copy_constructible<T>::value}} is {{c|true}}.
 +
* Otherwise, {{c|const T&}}.
  
 
===Parameters===
 
===Parameters===
{{param list begin}}
+
{{par begin}}
{{param list item | x | the object to be moved or copied}}
+
{{par|x|the object to be moved or copied}}
{{param list end}}
+
{{par end}}
  
 
===Return value===
 
===Return value===
 +
{{c|std::move(x)}} or {{c|x}}, depending on exception guarantees.
  
{{cpp|std::move(x)}}
+
===Complexity===
 +
Constant.
  
===Exceptions===
+
===Notes===
{{noexcept}}
+
This is used, for example, by {{lc|std::vector::resize}}, which may have to allocate new storage and then move or copy elements from old storage to new storage. If an exception occurs during this operation, {{lc|std::vector::resize}} undoes everything it did to this point, which is only possible if {{tt|std::move_if_noexcept}} was used to decide whether to use move construction or copy construction (unless copy constructor is not available, in which case move constructor is used either way and the strong exception guarantee may be waived).
  
 
===Example===
 
===Example===
 
{{example
 
{{example
|
+
|code=
| code=
+
 
#include <iostream>
 
#include <iostream>
 
#include <utility>
 
#include <utility>
Line 39: Line 38:
 
{
 
{
 
     Bad() {}
 
     Bad() {}
     Bad(Bad&&) // may throw
+
     Bad(Bad&&) // may throw
 
     {
 
     {
 
         std::cout << "Throwing move constructor called\n";
 
         std::cout << "Throwing move constructor called\n";
Line 56: Line 55:
 
         std::cout << "Non-throwing move constructor called\n";
 
         std::cout << "Non-throwing move constructor called\n";
 
     }
 
     }
     Good(const Good&) {};
+
     Good(const Good&) noexcept // will NOT throw
 +
    {
 +
        std::cout << "Non-throwing copy constructor called\n";
 +
    }
 
};
 
};
  
Line 63: Line 65:
 
     Good g;
 
     Good g;
 
     Bad b;
 
     Bad b;
     Good g2 = std::move_if_noexcept(g);
+
     [[maybe_unused]] Good g2 = std::move_if_noexcept(g);
     Bad b2 = std::move_if_noexcept(b);
+
     [[maybe_unused]] Bad b2 = std::move_if_noexcept(b);
 
}
 
}
| output=
+
|output=
 
Non-throwing move constructor called
 
Non-throwing move constructor called
 
Throwing copy constructor called
 
Throwing copy constructor called
 
}}
 
}}
  
===Complexity===
+
===See also===
Constant
+
{{dsc begin}}
 +
{{dsc inc|cpp/utility/dsc forward}}
 +
{{dsc inc|cpp/utility/dsc move}}
 +
{{dsc end}}
  
===See also===
+
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
{{dcl list begin}}
+
{{dcl list template | cpp/utility/dcl list forward}}
+
{{dcl list template | cpp/utility/dcl list move}}
+
{{dcl list end}}
+

Latest revision as of 13:10, 13 July 2024

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
Integer comparison functions
(C++20)(C++20)(C++20)  
(C++20)
Swap and type operations
(C++14)
(C++11)
(C++11)
(C++11)
move_if_noexcept
(C++11)
(C++17)
Common vocabulary types
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
Elementary string conversions
(C++17)
(C++17)

 
Defined in header <utility>
template< class T >
/* see below */ move_if_noexcept( T& x ) noexcept;
(since C++11)
(constexpr since C++14)

std::move_if_noexcept obtains an rvalue reference to its argument if its move constructor does not throw exceptions or if there is no copy constructor (move-only type), otherwise obtains an lvalue reference to its argument. It is typically used to combine move semantics with strong exception guarantee.

The return type of std::move_if_noexcept is:

Contents

[edit] Parameters

x - the object to be moved or copied

[edit] Return value

std::move(x) or x, depending on exception guarantees.

[edit] Complexity

Constant.

[edit] Notes

This is used, for example, by std::vector::resize, which may have to allocate new storage and then move or copy elements from old storage to new storage. If an exception occurs during this operation, std::vector::resize undoes everything it did to this point, which is only possible if std::move_if_noexcept was used to decide whether to use move construction or copy construction (unless copy constructor is not available, in which case move constructor is used either way and the strong exception guarantee may be waived).

[edit] Example

#include <iostream>
#include <utility>
 
struct Bad
{
    Bad() {}
    Bad(Bad&&) // may throw
    {
        std::cout << "Throwing move constructor called\n";
    }
    Bad(const Bad&) // may throw as well
    {
        std::cout << "Throwing copy constructor called\n";
    }
};
 
struct Good
{
    Good() {}
    Good(Good&&) noexcept // will NOT throw
    {
        std::cout << "Non-throwing move constructor called\n";
    }
    Good(const Good&) noexcept // will NOT throw
    {
        std::cout << "Non-throwing copy constructor called\n";
    }
};
 
int main()
{
    Good g;
    Bad b;
    [[maybe_unused]] Good g2 = std::move_if_noexcept(g);
    [[maybe_unused]] Bad b2 = std::move_if_noexcept(b);
}

Output:

Non-throwing move constructor called
Throwing copy constructor called

[edit] See also

(C++11)
forwards a function argument and use the type template argument to preserve its value category
(function template) [edit]
(C++11)
converts the argument to an xvalue
(function template) [edit]