PrevUpHomeNext

day-17: c++ concepts


concepts are c++ language feature that make c++ template programming funny.

Write a simplest concept

template <typename type_t20>
concept always_true = true;

template <always_true type_t00>
class my_class
{
};

int main()
{
	my_class<int> obj1;
	auto obj2 = my_class<char>{};
}

You see, always_true is a concept, it is assigned true.

Basic Syntax

c++ concept basic syntax:

template <
	typename the_constrait_type,
	typename other_type1,
	typename other_type2,
	... ... ...
>
concept the_concept_name = the_constrait_expression ;

Note:

The concept template might have more than one template parameters, the first parameter is the target type to be constrained, the rest parameters are used to constrain the first parameter.

Some c++ standard concept libraries

std::same_as

std::same_as constrains the target type (the first parameter) must be the same as the second type (the second parameter).

#include <concepts>

template <std::same_as<int> type_t00>
class test
{
};

int main()
{
	test<int> t1{};
	//test<const int> t2{};	// fail
	//test<unsigned int> t3{};	// fail
	//test<float> t4{};	// fail
}

The std::same_as should be declared like this:

template <typename param1, typename param2>
concept same_as = expression___ ;

The above example, template <std::same_as<int> type_t00>,
type_t00 will be passed as the first parameter: param1 ,
int will be passed as the second parameter: param2 .
type_t00 is the target constraint type.

std::integral

std::integral requires the type must be an integral type.

#include <concepts>

template <std::integral type_t00>
class test
{
};

int main()
{
	test<int> t0;	// OK
	test<long int> t1;	// OK
	test<unsigned int> t2;	// OK
	// test<float> t3;	// fail, float does not satisfy std::integral.
}

std::floating_point

std::floating_point requires the type must be a floating point type.

#include <concepts>

template <std::floating_point type_t00>
class test
{
};

int main()
{
	auto t1 = test<float>{};	// OK
	auto t2 = test<double>{};	// OK
	//auto t3 = test<int>{};	// fail. int does not satisfy std::floating_point.
}

Define concepts: requires expression

Define concepts

c++ example

Requires some op

template <typename type_t20>
concept has_int_get = requires (type_t20 value_ob)	// requires
{
	value_ob.get();	// It requires object of type_t20 has a method get()
};

class tt_class
{
public:
	void get()
	{
	}
};

template <has_int_get type_t00>
class test
{
};

int main()
{
	test<tt_class> t1{};	// OK: tt_class is a type that has a method get().
	//test<int> t2{};	// fail. int does not have a method get().
}

The concept has_int_get requires the type has a method .get .

Requires returning a required type

#include <concepts>

template <typename type_t20>
concept has_int_get = requires (type_t20 value_ob)	// requires
{
	// Requires the return type is the same as float.
	{value_ob.get()} -> std::same_as<float>;
};

class tt_class
{
public:
	int get() {return 0;}
};

class pp_class
{
public:
	float get() {return 1.2f;}
};

template <has_int_get type_t00>
class test
{
};

int main()
{
	//auto t1 = test<tt_class>{};	// fail. tt_class::get does not return float.
	auto t2 = test<pp_class>{};	// OK
}

The concept has_int_get requires the type must have a method .get,
and that method must return a type that is the same as float .

Although tt_class has a method get, but it returns int, not float .

pp_class has a method get, and it returns float .

So, tt_class does not satisfy the concept has_int_get ,
pp_class satisfies the concept has_int_get .







Written on Nov 27, 2024

Back to index

Index

cpp/c++

c++ std::exception:

std::cout.write(err.data(), err.size());

std::cout << std::endl;

caught:

  ===================================
  #  The c++ programming language.  #
  #                                 #
  #  Join c++ Discord: yZcauUAUyC   #
  #  Deck                           #
  ===================================

Home: cppfx.xyz

K


PrevUpHomeNext