>>109886553
it gets better
check this out
class thread_wrapper_c
{
using thread_fn_t = void(void const*) noexcept;
using attr_getter_fn_t = thread_attributes_s(void const*) noexcept;
attr_getter_fn_t* const attr_getter_k{nullptr};
thread_fn_t* const external_entry_function_k{nullptr};
thread_fn_t* const external_init_function_k{nullptr};
thread_fn_t* const external_exit_function_k{nullptr};
void* const thread_k{nullptr};
friend void thread_entry(thread_wrapper_c const& object) noexcept { object.external_entry_function_k(object.thread_k); }
friend void thread_init(thread_wrapper_c const& object) noexcept { object.external_init_function_k(object.thread_k); }
friend void thread_exit(thread_wrapper_c const& object) noexcept { object.external_exit_function_k(object.thread_k); }
friend thread_attributes_s thread_attr(thread_wrapper_c const& object) noexcept { return object.attr_getter_k(object.thread_k); }
public:
template <typename T>
thread_wrapper_c(T& thread) noexcept
: attr_getter_k{[](void const* object) noexcept -> thread_attributes_s { return (*static_cast<T const*>(object)).attributes; }}
, external_entry_function_k{[](void const* object) noexcept -> void { thread_entry(*static_cast<T const*>(object)); }}
, external_init_function_k{[](void const* object) noexcept -> void { thread_init(*static_cast<T const*>(object)); }}
, external_exit_function_k{[](void const* object) noexcept -> void { thread_exit(*static_cast<T const*>(object)); }}
, thread_k{std::addressof(thread)}
{
}
};