JHe*_*eni 2 c++ c++-concepts c++20
Hey I'm trying to design some Interfaces without any runtime overhead using c++20 concepts.
I came up with the following (simplified) concept
/**
* @brief This concept defines an OSA Interface
*/
template<typename T, typename Task_T>
concept OSA_Layer_T = requires (T a) {
{T::getName(a)} -> std::same_as<std::string>; ///< Returns the name of the task (if no name is available return the ID as string)
{T::getId(a)} ->std::same_as<Task_T>; ///< returns the (underlying) ID of the task
};
Run Code Online (Sandbox Code Playgroud)
Since every OS has it's own internal Task Handle Type (and I do not want to use void*) I need to pass the actual Task Handle as a template parameter to my concept
However I'm unsure how to define a class using this template
I have tried the following
This does not work because Task_T is missing
template<typename String_Type_T, OSA_Layer_T TaskType_T>
class Foo
{
};
Run Code Online (Sandbox Code Playgroud)
This does not work either
template<typename Task_T>
template<typename String_Type_T, OSA_Layer_T<Task_T> TaskType_T>
class Foo
{
};
Run Code Online (Sandbox Code Playgroud)
Could you help me out here? Thx :)
Edit:
To clarify: This OSA is supposed to hide embedded RTOS. Most embedded RTOS (like FreeRTOS, EmbOS, RTX) are written in C, therefore the OSA class is just a collection of static members calling the actual RTOS functions written in C) Usally you would implement this interface using virtual functions. However the goal of this is to reduce the overhead as much as possible. Usually on embedded targets we link statically, therefore all unused template functions are discarded automatically. Removing unused members is not possible if the members are virtual.
(CMSIS from ARM is available as an OSA for embedded RTOS. However IMHO CMSIS has some downsides like the overuse of void*. This is why I'd like to create a type safe OSA)
由于每个操作系统都有自己的内部任务句柄类型(并且我不想使用
void*),因此我需要将实际的任务句柄作为模板参数传递给我的概念
第二部分实际上并不是第一部分的结果。如果每个操作系统都有自己的内部任务句柄类型,则方法应该是将其作为概念的一部分。因为只有一个接口:OSA_Layer_T。
使用更熟悉的概念:迭代器可能更容易理解这一点。迭代器有一个它们取消引用的类型(不幸的是,这被称为reference。不幸的是,因为它并不总是引用类型,它可能只是int)。但你不想这样定义你的概念:
template <typename I, typename Reference>
concept Iterator = /* ... */;
Run Code Online (Sandbox Code Playgroud)
因为它不像Iterator<int>并且Iterator<string const&>是不同的接口 - 如果类型是 an Iterator,那么它具有某种reference类型,您应该能够请求该类型,并且这并不会真正影响其余的任何内容。
这通常称为关联类型。
对于原问题,表述应该是:
template<typename T>
concept OsaLayer = requires (T a) {
{ T::getName(a) } -> std::same_as<std::string>;
typename T::task_type;
{ T::getId(a) } -> std::same_as<typename T::task_type>;
};
Run Code Online (Sandbox Code Playgroud)
如果您需要能够非 intrisuviely提供任务类型(如果您不控制类型OsaLayer),那么您可以这样做:
// specialize this for types that need to be OsaLayer's
template <typename T> struct task_type;
template <typename T> using task_type_t = typename task_type<T>::type;
template<typename T>
concept OsaLayer = requires (T a) {
{ T::getName(a) } -> std::same_as<std::string>;
typename task_type_t<T>;
{ T::getId(a) } -> std::same_as<task_type_t<T>>;
};
Run Code Online (Sandbox Code Playgroud)