C++20中头文件concepts的使用

      <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;
}

      执行结果如下图所示:

      GitHubhttps://github.com/fengbingchun/Messy_Test

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值