Skip to content

Instantly share code, notes, and snippets.

@elbeno
Last active April 5, 2018 17:02
Show Gist options
  • Save elbeno/4ba204a9e93923fc426907c2d36cb53b to your computer and use it in GitHub Desktop.
Save elbeno/4ba204a9e93923fc426907c2d36cb53b to your computer and use it in GitHub Desktop.
Setting required fields & optional fields in a type safe way
#include <iostream>
#include <string>
#include <vector>
template <uint32_t N>
struct request;
template <>
struct request<0>
{
constexpr static uint32_t OPT_FIELDS = 1 << 0;
constexpr static uint32_t REQ_FIELD1 = 1 << 1;
constexpr static uint32_t REQ_FIELD2 = 1 << 2;
constexpr static uint32_t ALL_FIELDS = OPT_FIELDS | REQ_FIELD1 | REQ_FIELD2;
std::string required1;
std::string required2;
std::vector<std::string> optionals;
};
template <uint32_t N>
struct request : request<N-1>
{
using request<0>::REQ_FIELD1;
using request<0>::REQ_FIELD2;
request<N & ~REQ_FIELD1>& set_required_field1(const std::string& s)
{
this->required1 = s;
return *this;
}
request<N & ~REQ_FIELD2>& set_required_field2(const std::string& s)
{
this->required2 = s;
return *this;
}
request& set_optional_field(const std::string& s)
{
this->optionals.push_back(s);
return *this;
}
};
auto make_request()
{
return request<request<0>::ALL_FIELDS>{};
}
template <uint32_t N>
auto send_request(const request<N>& req) = delete;
auto send_request(const request<request<0>::OPT_FIELDS>& req)
{
std::cout << "Send request: "
<< "req1 = " << req.required1
<< ", req2 = " << req.required2
<< ", opts = [";
for (const auto& o : req.optionals)
std::cout << o << ',';
std::cout << "]\n";
}
int main()
{
auto req = make_request()
.set_required_field1("foo")
.set_required_field2("bar")
.set_optional_field("baz")
.set_optional_field("quux")
.set_optional_field("wibble")
;
send_request(req);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment