Skip to content

Instantly share code, notes, and snippets.

@ktbarrett
Last active September 1, 2020 23:46
Show Gist options
  • Save ktbarrett/4a7e994d66d9d94acd2faa13cc615f10 to your computer and use it in GitHub Desktop.
Save ktbarrett/4a7e994d66d9d94acd2faa13cc615f10 to your computer and use it in GitHub Desktop.
It works! User defined conversion constructors
// Library code
#include <stdexcept>
#include <type_traits>
#include <utility>
namespace library {
template <typename T>
struct to_positive {
static const bool exists = false;
// can't define this here since Positive would have to be fully defined
// static Positive convert(T const&) { ... }
};
class Positive {
public:
using storage_type = int;
Positive(storage_type const& value)
: value_(value)
{
if (value_ <= 0) {
throw std::range_error("Value must be positive (> 0)");
}
}
// here we use the user defined conversion to define a generic
// conversion constructor, implicit or explicit is up to you
// perhaps you could even add that as a parameter to the conversion
// template!
template <
typename Convertible,
std::enable_if_t<to_positive<Convertible>::exists, int> = 0
>
Positive(Convertible const& value)
: Positive(to_positive<Convertible>::convert(value))
{
}
storage_type const& value() const noexcept { return value_; }
private:
storage_type value_ {0};
};
}
// User code
#include <string>
// define conversion for user type using a specialization of
// to_positive struct
template <>
struct library::to_positive<std::string>
{
static const bool exists = true;
static Positive convert(std::string const& s)
{
return Positive(std::stol(s));
}
};
namespace user {
using library::Positive;
using namespace std::string_literals;
void use()
{
auto p = Positive("567"s);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment