std::is_mov...structible,(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

Hey bestie πŸ’– welcome to the std::is_mov...structible,(3) page from the C++ Standard Libary manual. Buckle up, because this one is all about std::is_move_constructible, std::is_trivially_move_constructible, and std::is_nothrow_move_constructible. πŸŽ€

πŸ’– NAME πŸ’–

This page's name is literally:

std::is_move_constructible,std::is_trivially_move_constructible, - std::is_move_constructible,std::is_trivially_move_constructible,

No cap, that's the exact NAME line, trailing comma and all. πŸ’…


✨ Synopsis ✨

Defined in header <type_traits>.

template< class T >                     (1) (since C++11)
struct is_move_constructible;
template< class T >                     (2) (since C++11)
struct is_trivially_move_constructible;
template< class T >                     (3) (since C++11)
struct is_nothrow_move_constructible;

Okay so the member constant value gets decided like this:

  • Type trait (1) β€” if T is a referenceable type, value is std::is_constructible<T, T&&>::value.
  • Type trait (2) β€” if T is a referenceable type, value is std::is_trivially_constructible<T, T&&>::value.
  • Type trait (3) β€” if T is a referenceable type, value is std::is_nothrow_constructible<T, T&&>::value.
  • If T is not a referenceable type β€” value is false.
If T is not a complete type, (possibly cv-qualified) void, or an array of unknown bound, the behavior is undefined. 😭
If an instantiation of a template above depends, directly or indirectly, on an incomplete type, and that instantiation could yield a different result if that type were hypothetically completed, the behavior is undefined. πŸ’€
If the program adds specializations for any of the templates described on this page, the behavior is undefined. 🚨

πŸŽ€ Member constants πŸŽ€

  • value β€” true if T is move-constructible, false otherwise. It's a [static] public static member constant. πŸ’–

πŸ’… Member functions πŸ’…

  • operator bool β€” converts the object to bool, returns value (public member function).
  • operator() β€” returns value (C++14) (public member function).

πŸ¦‹ Member types πŸ¦‹

  • Type value_type β€” Definition: bool.
  • Type type β€” Definition: std::integral_constant<bool, value>.

🌸 Possible implementation 🌸

template<class T>
struct is_move_constructible :
    std::is_constructible<T, typename
std::add_rvalue_reference<T>::type> {};

template<class T>
struct is_trivially_move_constructible :
    std::is_trivially_constructible<T, typename
std::add_rvalue_reference<T>::type> {};

template<class T>
struct is_nothrow_move_constructible :
    std::is_nothrow_constructible<T, typename
std::add_rvalue_reference<T>::type> {};

⭐ Notes ⭐

  • Types without a move constructor, but with a copy constructor that accepts const T& arguments, satisfy std::is_move_constructible.
  • Move constructors are usually noexcept, since otherwise they are unusable in any code that provides strong exception guarantee.
  • In many implementations, std::is_nothrow_move_constructible also checks if the destructor throws because it is effectively noexcept(T(arg)). Same applies to std::is_trivially_move_constructible, which, in these implementations, also requires that the destructor is trivial: GCC bug 51452, LWG issue 2116.

πŸ”₯ Example πŸ”₯

// Run this code

#include <string>
#include <type_traits>

struct Ex1
{
    std::string str; // member has a non-trivial but non-throwing move constructor
};
static_assert(std::is_move_constructible_v<Ex1>);
static_assert(!std::is_trivially_move_constructible_v<Ex1>);
static_assert(std::is_nothrow_move_constructible_v<Ex1>);

struct Ex2
{
    int n;
    Ex2(Ex2&&) = default; // trivial and non-throwing
};
static_assert(std::is_move_constructible_v<Ex2>);
static_assert(std::is_trivially_move_constructible_v<Ex2>);
static_assert(std::is_nothrow_move_constructible_v<Ex2>);

struct NoMove1
{
    // prevents implicit declaration of default move constructor;
    // however, the class is still move-constructible because its
    // copy constructor can bind to an rvalue argument
    NoMove1(const NoMove1&) {}
};
static_assert(std::is_move_constructible_v<NoMove1>);
static_assert(!std::is_trivially_move_constructible_v<NoMove1>);
static_assert(!std::is_nothrow_move_constructible_v<NoMove1>);

struct NoMove2
{
    // Not move-constructible since the lvalue reference
    // can't bind to the rvalue argument
    NoMove2(NoMove2&) {}
};
static_assert(!std::is_move_constructible_v<NoMove2>);
static_assert(!std::is_trivially_move_constructible_v<NoMove2>);
static_assert(!std::is_nothrow_move_constructible_v<NoMove2>);

int main() {}

πŸ‘‘ See also πŸ‘‘

  • is_constructible, is_trivially_constructible, is_nothrow_constructible (C++11) (C++11) (C++11) β€” checks if a type has a constructor for specific arguments (class template) ✨
  • is_default_constructible, is_trivially_default_constructible, is_nothrow_default_constructible (C++11) (C++11) (C++11) β€” checks if a type has a default constructor (class template) πŸ’–
  • is_copy_constructible, is_trivially_copy_constructible, is_nothrow_copy_constructible (C++11) (C++11) (C++11) β€” checks if a type has a copy constructor (class template) πŸŽ€
  • move_constructible (C++20) β€” specifies that an object of a type can be move constructed (concept) πŸ¦‹
  • move (C++11) β€” obtains an rvalue reference (function template) πŸ”₯
  • move_if_noexcept (C++11) β€” obtains an rvalue reference if the move constructor does not throw (function template) πŸ’…

Source: http://cppreference.com Β· version/date: 2024.06.10 Β· page: std::is_mov...structible,(3) β€” mwah, hope that slayed for you πŸ’‹πŸŒˆ

πŸ“¦ where this page comes from