Created
April 12, 2019 06:07
-
-
Save eao197/eb73f67ba10ccb8322f42e9368c0b2a3 to your computer and use it in GitHub Desktop.
CTRP and C++ template magic for compile-time control (more advanced version)
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; } | |
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_; } | |
const auto & data() const { return data_; } | |
auto & data() { return data_; } | |
}; | |
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 actual_type::template clone_if_necessary< | |
msg_count_status_t::defined >( self_reference() ); | |
} | |
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; | |
}; | |
template< | |
msg_count_status_t Msg_Count_Status, | |
template<msg_count_status_t> typename T> | |
struct cloner_t | |
{ | |
template<msg_count_status_t New_Msg_Count_Status> | |
static std::enable_if_t< | |
New_Msg_Count_Status != Msg_Count_Status, | |
T<New_Msg_Count_Status> > | |
clone_if_necessary(const T<Msg_Count_Status> & self) | |
{ | |
return { self.data() }; | |
} | |
template<msg_count_status_t New_Msg_Count_Status> | |
static std::enable_if_t< | |
New_Msg_Count_Status == Msg_Count_Status, | |
T<Msg_Count_Status>& > | |
clone_if_necessary(T<Msg_Count_Status> & self) | |
{ | |
return self; | |
} | |
}; | |
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> > | |
, public cloner_t<Msg_Count_Status, receive_specific_params_t> | |
{ | |
using base_type = basic_params_t< | |
receive_specific_data_t, | |
receive_specific_params_t<Msg_Count_Status> >; | |
public : | |
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; | |
} | |
struct select_specific_data_t final : public basic_data_t | |
{ | |
int select_payload_{}; | |
select_specific_data_t() = default; | |
}; | |
template< msg_count_status_t Msg_Count_Status > | |
class select_specific_params_t final | |
: public basic_params_t< | |
select_specific_data_t, | |
select_specific_params_t<Msg_Count_Status> > | |
, public cloner_t<Msg_Count_Status, select_specific_params_t> | |
{ | |
using base_type = basic_params_t< | |
select_specific_data_t, | |
select_specific_params_t<Msg_Count_Status> >; | |
public : | |
select_specific_params_t() = default; | |
select_specific_params_t(typename base_type::data_type data) | |
: base_type{ std::move(data) } | |
{} | |
decltype(auto) select_payload(int v) | |
{ | |
this->data().select_payload_ = v; | |
return *this; | |
} | |
int select_payload() const { return this->data().select_payload_; } | |
}; | |
select_specific_params_t<msg_count_status_t::undefined> | |
make_select_params() | |
{ | |
return {}; | |
} | |
template<msg_count_status_t Msg_Count_Status> | |
void do_something(const select_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 << "select_payload: " << params.select_payload() << std::endl; | |
} | |
int main() | |
{ | |
std::cout << "*** receive ***" << std::endl; | |
do_something( make_receive_params(42).handle_all().common_payload(13) ); | |
std::cout << "\n*** select ***" << std::endl; | |
do_something( | |
make_select_params() | |
.extract_n(20).common_payload(13) | |
.select_payload(55) | |
.handle_n(3) ); | |
} | |
// 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