C ++的std :: is_trivially_move_assignable使用示例
C ++是一种通用编程语言,广泛用于系统软件编写和应用程序开发。其中的std :: is_trivially_move_assignable是一个C ++标准库工具。它能够确定一个类型是否支持平凡的移动赋值运算。这个函数返回一个bool值,指示这个类型是否支持平凡的移动赋值运算。
使用前提
C ++14标准中引入了std :: is_trivially_move_assignable,但C ++11标准库中也有一个is_trivially_move_assignable函数,这里我们主要讲解C ++ 14中的std :: is_trivially_move_assignable。使用前提是:
- C ++14标准及以上;
- 使用g++ 5.1.0或其他支持C ++14标准的编译器;
语法
以下是std :: is_trivially_move_assignable的基本语法:
#include <type_traits>
std::is_trivially_move_assignable<T>::value
其中:
表示引用标准库头文件; - T表示一个类型;
- ::value在编译时求值为true或false。
用法说明
当使用std :: is_trivially_move_assignable测试一个类型时,如果该类型支持平凡的移动赋值运算,则函数返回值为true,否则返回值为false。
示例如下:
#include <iostream>
#include <type_traits>
using namespace std;
class A {
public:
A& operator=(A&&)=delete;
};
class B {
public:
B& operator=(B&&)=default;
};
class C {
public:
C& operator=(C&&)noexcept;
};
int main()
{
cout<<boolalpha;
cout<<is_trivially_move_assignable<A>::value<<endl; //false
cout<<is_trivially_move_assignable<int>::value<<endl; //true
cout<<is_trivially_move_assignable<B>::value<<endl; //true
cout<<is_trivially_move_assignable<C>::value<<endl; //true
return 0;
}
这里使用了两种类:A和B。类A显式禁用了其移动赋值运算符。类B支持默认移动赋值运算符。可以看到,在定义类A时,is_trivially_move_assignable::value返回的是false,而is_trivially_move_assignable::value返回的是true。此外,无论类型是否使用noexcept的移动赋值运算,std :: is_trivially_move_assignable也会正确处理它们。
实际应用
std :: is_trivially_move_assignable可用于许多应用场景,这里介绍两个实例:
例1
std :: is_trivially_move_assignable有时可用于在程序中进行类型选择。比如,我们想创建一个缓冲区,并且使用平凡的拷贝和移动语义将数据从一个缓冲区移到另一个缓冲区。
template<typename T>
class buffer
{
T * data;
bool destroyed = false;
public:
buffer() : data(new T) {}
buffer(buffer&& other)
:data(other.data)
{
destroyed = other.destroyed;
other.destroyed = true;
}
buffer& operator=(buffer&& other)
{
if (std::is_trivially_move_assignable<T>::value) // 平凡的移动赋值运算符
{
data = other.data;
destroyed = other.destroyed;
other.destroyed = true;
}
else //不是平凡的移动赋值运算符
{
if (!destroyed) {
data->~T();
destroyed = true;
}
data = other.data;
other.data = nullptr;
}
return *this;
}
// ....
};
这里,如果std :: is_trivially_move_assignable
返回true,则使用平凡的拷贝语义进行移动,否则使用非平凡的拷贝语义进行移动。
例2
std :: is_trivially_move_assignable也可用于确定对象是否可以通过传递一个移动的对象和其他参数来构造。比如,我们希望为一个存储在容器中的对象创建一个可选值。在以下代码中,如果类型T支持平凡的移动赋值运算符,则使用一个移动拷贝构造函数进行构造,否则使用一个带有常量L值引用参数的构造函数:
template<typename T>
class optional {
T* ptr_ = nullptr;
public:
optional(T&& value) :
ptr_( std::is_trivially_move_constructible<T>::value ?
new T(static_cast<T&&>(value)) :
new T(static_cast<const T&>(value)) ) {}
// ....
};
结论
std :: is_trivially_move_assignable是一个非常有用的类型工具,可用于在C ++程序中对不同类型进行区分或选择。在大多数情况下,如果类型支持平凡的移动赋值运算,则可以使用std :: is_trivially_move_assignable来优化程序的性能。