Skip to content

Instantly share code, notes, and snippets.

@eao197
Created April 11, 2019 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save eao197/7024fa8181352e47703ccc0f1fc47113 to your computer and use it in GitHub Desktop.
Save eao197/7024fa8181352e47703ccc0f1fc47113 to your computer and use it in GitHub Desktop.
CTRP and C++ template magic for compile-time control
#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