<concepts>是C++20中新增加的头文件,此头文件是concepts库的一部分,主要用于模板编程、泛型编程。包括
1.core language concepts:
std::same_as:指定一种类型(type)与另一种类型是否相同。
std::derived_from:指定一种类型是否派生自另一种类型。
std::convertible_to:指定一种类型是否可以隐式转换为另一种类型。
std::common_reference_with:指定两种类型是否共享一个公共的引用类型。
std::common_with:指定两种类型是否共享一个公共类型。
std::integral:指定类型是否为整数类型。
std::signed_integral:指定类型是否为有符号的整数类型。
std::unsigned_integral:指定类型是否为无符号的整数类型。
std::floating_point:指定类型是否为浮点类型。
std::assignable_from:指定一种类型是否可以从另一种类型分配。
std::swappable、std::swappable_with:指定类型是否可以交换。
std::destructible:指定该类型的对象是否可以被销毁。
std::default_initializable:指定类型的对象是否可以默认构造。
std::move_constructible:指定类型的对象是否可以进行移动构造。
std::copy_constructible:指定类型的对象可以被拷贝构造和移动构造。
namespace {
struct A{
int x, y;
//A(int x,int y):x(x), y(y) {}
bool operator==(const A& other) const
{
return x == other.x && y == other.y;
}
//bool operator!=(const A& other) const
//{
// return !(*this == other);
//}
};
struct B{
int x, y;
auto operator<=>(const B& other) const = default;
auto operator()() const
{
return x % 2 == 0;
}
};
struct C : public A{
C(C&&) = delete;
C& operator=(C&&) = delete;
};
struct D : private A{
int x, y;
D() = delete;
auto operator()()
{
return (x + y);
}
};
using INT = int;
using FLOAT = float;
} // namespace
int test_concepts_core_lanuage()
{
static_assert(std::same_as<A, B> == false, "A and B are not the same"); // std::is_same_v<T, U>
static_assert(std::derived_from<C, A> == true);
static_assert(std::derived_from<A, C> == false);
static_assert(!std::derived_from<D, A>);
static_assert(std::convertible_to<C, A>);
static_assert(std::common_reference_with<C, A>);
static_assert(std::common_with<C, A>);
static_assert(std::integral<INT>);
static_assert(!std::integral<FLOAT>);
static_assert(std::signed_integral<INT>);
static_assert(!std::unsigned_integral<INT>);
static_assert(std::floating_point<FLOAT>);
static_assert(std::assignable_from<std::string&, std::string>);
static_assert(!std::assignable_from<std::string, std::string>);
static_assert(!std::assignable_from<std::string, std::string&>);
static_assert(std::default_initializable<A>);
static_assert(std::move_constructible<B>);
static_assert(std::copy_constructible<D>);
return 0;
}
2.comparison concepts:
std::equality_comparable,std::equality_comparable_with:用于检查指定类型是否支持==运算符。
std::totally_ordered,std::totally_ordered_with:用于检查指定类型是否支持所有比较操作符。
int test_concepts_comparison()
{
static_assert(std::equality_comparable<A>);
static_assert(std::equality_comparable<B>);
static_assert(std::equality_comparable<C>);
static_assert(!std::totally_ordered<A>);
static_assert(std::totally_ordered<B>);
return 0;
}
3.object concepts:
std::movable:指定类型的对象是否可以进行移动构造和swapped。
std::copyable:指定类型的对象是否可以进行拷贝、移动和swapped。
std::semiregular:指定类型的对象是否可以进行拷贝、移动、swapped和默认构造。
std::regular:指定类型是否是regular的,即:
template<class T>
concept regular = std::semiregular<T> && std::equality_comparable<T>;
int test_concepts_object()
{
static_assert(std::movable<A>);
static_assert(std::movable<B>);
static_assert(!std::movable<C>);
static_assert(std::copyable<A>);
static_assert(std::copyable<B>);
static_assert(!std::copyable<C>);
static_assert(std::semiregular<A>);
static_assert(!std::semiregular<D>);
static_assert(std::regular<A>);
static_assert(!std::regular<D>);
return 0;
}
4.callable concepts:
std::invocable、std::regular_invocable:检查给定的可调用对象是否可以被调用,即是否含有operator()。
std::predicate:指定可调用类型是否是布尔谓词(boolean predicate)。
std::relation:指定可调用类型是否是二元关系(binary relation)。
int test_concepts_callable()
{
static_assert(!std::regular_invocable<A>);
static_assert(std::regular_invocable<D>);
static_assert(!std::predicate<A>);
static_assert(std::predicate<B>);
static_assert(!std::relation<A, B, C>);
return 0;
}
5.customization point objects:
std::ranges::swap:交换两个对象的值。
int test_concepts_customization_point_objects()
{
int x{ 1 }, y{ -1 };
std::cout << "x=" << x << ", y=" << y << std::endl;
std::ranges::swap(x, y);
std::cout << "x=" << x << ", y=" << y << std::endl;
std::string addr1{ "TianJin" }, addr2{ "BeiJing" };
std::cout << "addr1=" << addr1 << ", addr2=" << addr2 << std::endl;
std::ranges::swap(addr1, addr2);
std::cout << "addr1=" << addr1 << ", addr2=" << addr2 << std::endl;
auto print = [](const std::vector<int>& vec) {
for (const auto& value : vec)
std::cout << value << ",";
std::cout << std::endl;
};
std::vector vec1{ 1, 2, 3 }, vec2{ -1,-2,-3,-4,-5 };
std::cout << "vec1: "; print(vec1);
std::cout << "vec2: "; print(vec2);
std::ranges::swap(vec1, vec2);
std::cout << "vec1: "; print(vec1);
std::cout << "vec2: "; print(vec2);
return 0;
}
执行结果如下图所示:
GitHub:https://github.com/fengbingchun/Messy_Test