Created
April 11, 2019 17:30
-
-
Save eao197/7024fa8181352e47703ccc0f1fc47113 to your computer and use it in GitHub Desktop.
CTRP and C++ template magic for compile-time control
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
enum class msg_count_status_t | |
{ | |
undefined, | |
defined | |
}; | |
struct basic_data_t | |
{ | |
int to_extract_{}; | |
int to_handle_{}; | |
int common_payload_{}; | |
}; | |
template<typename Basic_Data> | |
class basic_data_holder_t | |
{ | |
private : | |
Basic_Data data_; | |
protected : | |
void set_to_extract(int v) { data_.to_extract_ = v; } | |
void set_to_handle(int v) { data_.to_handle_ = v; } | |
void set_common_payload(int v) { data_.common_payload_ = v; } | |
const auto & data() const { return data_; } | |
public : | |
basic_data_holder_t() = default; | |
basic_data_holder_t(Basic_Data data) : data_{std::move(data)} {} | |
int to_extract() const { return data_.to_extract_; } | |
int to_handle() const { return data_.to_handle_; } | |
int common_payload() const { return data_.common_payload_; } | |
}; | |
template<typename Data, typename Derived> | |
class basic_params_t : public basic_data_holder_t<Data> | |
{ | |
using base_type = basic_data_holder_t<Data>; | |
public : | |
using actual_type = Derived; | |
using data_type = Data; | |
protected : | |
actual_type & self_reference() | |
{ return static_cast<actual_type &>(*this); } | |
decltype(auto) clone_as_defined() | |
{ | |
return self_reference().template clone_if_necessary< | |
msg_count_status_t::defined >(); | |
} | |
public : | |
basic_params_t() = default; | |
basic_params_t(data_type data) : base_type{std::move(data)} {} | |
decltype(auto) handle_all() | |
{ | |
this->set_to_handle(0); | |
return clone_as_defined(); | |
} | |
decltype(auto) handle_n(int v) | |
{ | |
this->set_to_handle(v); | |
return clone_as_defined(); | |
} | |
decltype(auto) extract_n(int v) | |
{ | |
this->set_to_extract(v); | |
return clone_as_defined(); | |
} | |
actual_type & common_payload(int v) | |
{ | |
this->set_common_payload(v); | |
return self_reference(); | |
} | |
using base_type::common_payload; | |
}; | |
struct receive_specific_data_t final : public basic_data_t | |
{ | |
int receive_payload_{}; | |
receive_specific_data_t() = default; | |
receive_specific_data_t(int v) : receive_payload_{v} {} | |
}; | |
template< msg_count_status_t Msg_Count_Status > | |
class receive_specific_params_t final | |
: public basic_params_t< | |
receive_specific_data_t, | |
receive_specific_params_t<Msg_Count_Status> > | |
{ | |
using base_type = basic_params_t< | |
receive_specific_data_t, | |
receive_specific_params_t<Msg_Count_Status> >; | |
public : | |
template<msg_count_status_t New_Msg_Count_Status> | |
std::enable_if_t< | |
New_Msg_Count_Status != Msg_Count_Status, | |
receive_specific_params_t<New_Msg_Count_Status> > | |
clone_if_necessary() const | |
{ | |
return { this->data() }; | |
} | |
template<msg_count_status_t New_Msg_Count_Status> | |
std::enable_if_t< | |
New_Msg_Count_Status == Msg_Count_Status, | |
receive_specific_params_t& > | |
clone_if_necessary() | |
{ | |
return *this; | |
} | |
receive_specific_params_t(int receive_payload) | |
: base_type{ typename base_type::data_type{receive_payload} } | |
{} | |
receive_specific_params_t(typename base_type::data_type data) | |
: base_type{ std::move(data) } | |
{} | |
int receive_payload() const { return this->data().receive_payload_; } | |
}; | |
receive_specific_params_t<msg_count_status_t::undefined> | |
make_receive_params(int receive_payload) | |
{ | |
return {receive_payload}; | |
} | |
template<msg_count_status_t Msg_Count_Status> | |
void do_something(const receive_specific_params_t<Msg_Count_Status> & params) | |
{ | |
static_assert( | |
Msg_Count_Status == msg_count_status_t::defined, | |
"message count to be processed/extracted should be defined " | |
"by using handle_all()/handle_n()/extract_n() methods" ); | |
std::cout << "to_handle: " << params.to_handle() << std::endl; | |
std::cout << "to_extract: " << params.to_extract() << std::endl; | |
std::cout << "common_payload: " << params.common_payload() << std::endl; | |
std::cout << "receive_payload: " << params.receive_payload() << std::endl; | |
} | |
int main() | |
{ | |
do_something( make_receive_params(42).handle_all().common_payload(13) ); | |
} | |
// vim:ts=3:sts=3:sw=3:expandtab |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment