Compiler-enforced semantic types - c++

Say I have a class representing automata, whose states are numbered (using state_t = unsigned) and whose transitons are also numbered (using transition_t = unsigned). Of course at some point I end up messing some calls because transition_t and state_t are the same type, so the compiler does not enforce the (semantic) type safety. That's easy to workaround by using a small class templated by a tag (struct transition_tag {}; struct state_tag {};), so now transition_t and state_t are incompatible, good!
/// Lightweight state/transition handle (or index).
template <typename Tag>
struct index_t_impl
{
using index_t = unsigned;
constexpr index_t_impl(index_t i)
: s{i}
{}
// Disallow index1_t i{index2_t{42}};
template <typename T>
index_t_impl(index_t_impl<T> t) = delete;
bool operator==(index_t_impl t) const
{
return s == t.s;
}
// Disallow index1_t{42} == index2_t{42};
template <typename T>
bool operator==(index_t_impl<T> t) const = delete;
/// Default ctor to please containers.
index_t_impl() = default;
constexpr operator index_t() const { return s; }
/// Be compliant with Boost integer ranges.
index_t_impl& operator++() { ++s; return *this; }
/// Be compliant with Boost integer ranges.
index_t_impl& operator--() { --s; return *this; }
private:
index_t s;
};
Further, I have two structures which are very much alike:
predecessors_t maps from a transition to its predecessor transition (in the shortest path). For efficiency, it's a std::vector<transition_t>.
path_t is a list of transition indexes. For efficiency it's a std::vector<transition_t>.
And then again I have this issue that I use std::vector<transition_t> for two completely different purposes. Of course, I could again introduce a wrapper templated by a tag, but then things become messy again. Public inheritance is very tempting (Thou shalt not inherit from std::vector)!
But really, I'm tired of ad-hoc solutions each time I want to introduce new types that are exactly like the base type, but just incompatible. Are there any recommendations on this regard? The public inheritance is really attractive, but wouldn't it introduce code bloat with tons on extra instantiations? Maybe the public composition (struct predecessors_t { std::vector<transition_t> v; };) as recommended by Crashworks (https://stackoverflow.com/a/4353276/1353549) is a better option that scales better?
Is there anything in sight in the future of C++ to address this new?

This issue of getting compiler-enforced semantic types can crop up in all sorts of situations, from your situation to co-ordinate systems with different origins (where the values are all the same type (eg. int), but semantically, the types must not be mixed, because they represent offsets from different origins (x,y,z=0,0,0)--this occurs frequently in mathematics, where, when graphing the quadrant with positive x and y, the origin is in the lower left, and computer science where it is very common to place the origin upper left) to spaceship navigation (more on this last below).
In 2012, Bjarne Stroustrup gave an interesting talk on what he called type-rich programming introducing compiler-enforced semantic type safety with C++11 using templates, user-defined literals, a claimed no run-time overhead implementation and even tales of lessons learned from the Mars Climate Observer snafu ($350M spacecraft + mission lost because of lack of enforced semantic type safety). You can see the part of the talk where he covers semantic types here: https://youtu.be/0iWb_qi2-uI?t=19m6s
I've written up a sample code excerpt based on Stroustrup's demo code, updated to current standards and with the required operator overloads implemented). Unlike Bjarne's example, this one actually compiles. ;)
Gist of this code can be found here: https://gist.github.com/u-007d/361221df5f8c7f3466f0f09dc96fb1ba
//Compiled with clang -std=c++14 -Weverything -Wno-c++98-compat main.cpp -o main
#include <iostream>
#include <string>
template<int M, int K, int S> //Meters, Kilograms, Seconds (MKS)
struct Unit
{
enum { m=M, kg=K, s=S };
};
template<typename Unit> //a magnitude with a unit
struct Value
{
double val; //the magnitude
constexpr explicit Value(double d) : val(d) {} //construct a Value from a double
};
//Basic Semantic Units for MKS domain
using Meter = Unit<1, 0, 0>;
using Kilogram = Unit<0, 1, 0>;
using Second = Unit<0, 0, 1>;
using Second2 = Unit<0, 0, 2>;
//Semantic Value Types for MKS domain
using Time = Value<Second>;
using Distance = Value<Meter>;
using Mass = Value<Kilogram>;
using Speed = Value<Unit<1, 0, -1>>; //Speed is meters/second
using Acceleration = Value<Unit<1, 0, -2>>; //Acceleration is meters/second^2
//Operator overloads to properly calculate units (incomplete; for demo purposes)
Speed operator/(const Distance& lhs, const Time& rhs)
{
return Speed(lhs.val / rhs.val);
}
Acceleration operator/(const Speed& lhs, const Time& rhs)
{
return Acceleration(lhs.val / rhs.val);
}
//Define literals
constexpr Distance operator"" _m(long double ld)
{
return Distance(static_cast<double>(ld));
}
constexpr Mass operator"" _kg(long double ld)
{
return Mass(static_cast<double>(ld));
}
constexpr Time operator"" _s(long double ld)
{
return Time(static_cast<double>(ld));
}
constexpr Acceleration operator"" _s2(long double ld)
{
return Acceleration(static_cast<double>(ld));
}
int main()
{
Speed sp = Distance(100)/Time(9.58); //Not bad, but units could be more convenient...
Distance d1 = 100.0_m; //A good distance to run a race
Speed sp1 = 100.0_m/9.58_s; //A human can run this fast
// Speed sp2 = 100.0_m/9.8_s2; //Error: speed is m/s, not m/s^2
// Speed sp3 = 100.0/9.8_s; //Error: 100 has no unit
Acceleration ac1 = sp1/0.5_s; //Faster than any human
return EXIT_SUCCESS;
}

Related

Literal with number and unit in an algebraic expression as argument

How to design a type that can take an expression in the form of an algebraic expression with numbers and units, where Speed is the type, 23m / 10s could be an expression?
Example:
change_speed(Speed s); // better: the meaning of s is specified
// ...
change_speed(2.3); // error: no unit
change_speed(23m / 10s); // meters per second
EDIT This question raised the question if a literal in the form of 23m is possible at all.
EDIT the reference to the source has been removed from question for clarity. It can be found here
What you have to do is design types that when the expression is evaluated it yields the desired type. With
change_speed(23m / 10s);
We need 23m and 10s to each yield a type that when you divide them together gives you a Speed. If we have a
struct Meter
{
Meter(double value) : value(value) {}
double value;
};
struct Second
{
Second(double value) : value(value) {}
double value;
}
Speeds operator /(const Meter& m, const Second& s)
{
return Speed(m.value / s.value);
}
Then we just need to define literal operators for Meter and Second like
Meter operator "" _m(double value) { return Meter(value); }
Second operator "" _s(double value) { return Second(value); }
we have to use _m and _s to make these valid user defined literals. All literals besides those provided by the standard must start with a _.
Then
change_speed(23_m / 10_s)
becomes
change_speed(Meter(23) / Second(10))
which becomes
change_speed(Speed(2.3))
It sounds like you want something like a units/dimensional analysis type system. See for example Boost.Units.
The fundamental (length, time, etc.) units are defined similarly to the duration types in std::chrono - just with more than one (time) distinct dimension. The arithmetic operators are implemented to combine units into correctly-dimensioned compound types.
So, rather than defining Speed as an independent type, it's derived from the fundamental Metre and Second types (which are themselves instances of the length and time units, which are probably instances of a generic unit template differentiated by tag types).
If you want to write user-defined literals for SI units, there are examples on codeproject or in this project on Github - I haven't read through either and can't vouch for their quality, but the idea is fine.
From reading the section of the CPPCoreGuidelines I think that maybe you are confusing the intent of the section. The main point is:
Express ideas directly in code.
The concept being that the code change_speed(double s) is ambiguous because the units and identity of type is ambiguous. Furthermore change_speed(double speed_m_p_s) is no good because it is easy to get wrong. The suggestion is therefore that you explicitly create the input type. Something like:
enum class SpeedType {
M_p_S
Km_p_H
...
}
template<SpeedType type>
class Speed {
explicit Speed(double speed)
... // Some fully specified class that represents a speed.
template<SpeedType type>
void change_speed(Speed<type> s) { ...
change_speed(2.3) // Implicit conversion means this will be an error
change_speed(Speed<M_p_S>(2.3)) // It is clear to the reader and compiler that this is of type speed
// with unit of M_p_S. Go to the Speed class for more information.
This is not a perfect example. But conceptually, this is what they are trying to inform you with this section.
If I've understood the question correctly.
For required behaviour you can use next c++ features.
1) We're need class describes time. There are need classes in STL.
std::chrono::seconds, std::chrono::minutes and other. For literals using you must add:
#include <chrono>
using namespace std::chrono_literals;
auto thetime = 10m; // it's okey. the time have type std::chrono::minutes
2) We're need class describes distances. There aren't distance classes in STL.
3) We're need class speed.
4) We're need division operator for distance and time argument.
class distance
{
public:
inline constexpr distance(
const unsigned long long millimeters) :
millimeters_{ millimeters }
{
}
inline long double millimeters() const noexcept
{
return (millimeters_);
}
inline long double santimeters() const noexcept
{
return (millimeters_ / 10);
}
inline long double meters() const noexcept
{
return (millimeters_ / 1000);
}
inline long double kilometers() const noexcept
{
return (millimeters_ / 1000000);
}
private:
long double millimeters_; // it's must be least dimension unit
};
inline constexpr distance operator""_mm(const unsigned long long value)
{
return distance{ value };
}
inline constexpr distance operator""_cm(const unsigned long long value)
{
return distance{ value * 10 };
}
inline constexpr distance operator""_m(const unsigned long long value)
{
return distance{ value * 1000 };
}
inline constexpr distance operator""_km(const unsigned long long value)
{
return distance{ value * 1000000 };
}
// !
// it's need the same operators"" only for long long argument types
// !
class speed
{
public:
// ...
speed(long double)
{
}
// ...
};
template <typename _Rep>
speed operator/(
const distance& the_distance,
const std::chrono::duration<_Rep>& the_time)
{
// divide by zero!
return speed{ the_distance / the_time };
}
void speed_test(const speed&)
{
}
void foo()
{
using namespace std::chrono_literals;
speed_test(100_km / 21s);
}

Compile-time constructor switch in C++

Is there some sort of compile-time switch statement that I can use to pass parameters to a constructor for a member variable? Right now, I have a controller (in the control systems sense, not the MVC sense) that I need to be able to configure its operating frequency at compile time and a filter whose parameters depend on the selected frequency. Here is a skeleton of how I've implemented it:
#include <cstdint>
class Filter {
public:
Filter(float p1, float p2) : p1(p1), p2{p2} {}
private:
float const p1;
float const p2;
};
class Controller {
public:
Controller(void) {}
private:
static constexpr uint32_t frequency = 200U;
Filter filter{frequency == 400U ? 3.0f : // p1
frequency == 200U ? 1.0f :
frequency == 50U ? 0.55f : 0f,
frequency == 400U ? 2.0f : // p2
frequency == 200U ? 9.0f :
frequency == 50U ? 37.1f : 0f,
};
static_assert(frequency == 400U || frequency == 200U || frequency == 50U, "Invalid frequency");
};
This is obviously very difficult to maintain for large numbers of frequencies, even for only two filter parameters (the real software has more). Every time I need to add support for a new frequency, I need to add code to n points in the code, where n is the number of parameters for the filter. What I would like is something like this:
Filter filter = frequency == 400U ? {3.0f, 2.0f} :
frequency == 200U ? {1.0f, 9.0f} :
frequency == 50U ? {0.55f, 37.1f} :
{0.0f, 0.0f};
Or, in my wilder dreams:
Filter filter = static_switch_map(frequency) {
400U: {3.0f, 2.0f},
200U: {1.0f, 9.0f},
50U: {0.55f, 37.1f},
};
The parameters for the filter are not formulaically determined and thus cannot be written as part of an expression. Some additional notes:
I am using c++14 extensions in clang and GNU C++.
I am open to using a higher c++ extension and compiler extensions specific to GNU C++, though c++14 in both clang and GNU C++ preferred. clang-only solutions are no good to me.
This is for use in an embedded environment; a run-time solution using switch plus new plus pointers is unacceptable because of the indirection performance hit, binary file bloat, and the un-safeness of memory allocation in the embedded environment.
The Filter class may be instantiated multiple times.
Solutions involving templates are okay; I'm only using floats right now because I'm porting someone's Matlab code, but I will eventually switch to fixed-point math.
Other solutions I have considered include:
Conditional compilation using macros and define (the frequency variable I'm using in the real code is a custom data type, so I'd need to use define and a C++ variable that have similar roles; I don't like the idea of having frequency defined in two locations -- that's going to lead to maintenance problems down the road).
Rewriting variables using a custom preprocessor during the build process. Too magical and will likely become a gotcha to someone in the future.
Enums. I haven't ruled these out, but I can't think of how to use them in a way that would improve the code without the abilities of Java enums and/or a Python-like *args expansion. Admittedly, I've only been writing C++ for about four months (non-consecutively) and only had a solid year of experience with C before that, so there's a good chance I'm missing something, syntax-wise.
Separate include file to contain the magic; in my project, all automatically generated files have a separate extension, so this works. However, I prefer to have simpler build scripts and keep as much of the logic in the C++ code as possible.
Put your switch in a factory method and make your constructor private, so that you are forced to use that method.
This way you'll have only one point to update in your code in future:
struct Filter {
static Filter create(int freq) {
switch(freq) {
case 0: return { 0, 1 };
case 2: return { 3, 7 };
default: return { 0, 0 };
}
}
private:
Filter(int, int) {}
};
int main() {
auto filter = Filter::create(2);
(void)filter;
}
If you want to use it also at compile-time, you can slightly change it as it follows (this requires C++14):
class Filter {
constexpr Filter(int i, int j)
: i{i}, j{j}
{}
public:
static constexpr Filter create(int freq) {
switch(freq) {
case 0: return { 0, 1 };
case 2: return { 3, 7 };
default: return { 0, 0 };
}
}
constexpr int get_i() const { return i; }
constexpr int get_j() const { return j; }
private:
int i;
int j;
};
int main() {
constexpr auto filter = Filter::create(2);
static_assert(filter.get_i() == 3, "!");
}
Of course, you can easily add a copy constructor or whatever to your Filter class. This is a minimal example to show how the pattern works, nothing more.
Another way to define them separately and use each constructor through a call to a factory method is based on delegating constructors:
template<int>
struct freq_tag {};
class Filter {
constexpr Filter(int i, int j)
: i{i}, j{j}
{}
constexpr Filter(freq_tag<0>): Filter{0, 1} {}
constexpr Filter(freq_tag<2>): Filter{3, 7} {}
template<int N>
constexpr Filter(freq_tag<N>): Filter{0, 0} {}
public:
template<int N>
constexpr static Filter create() {
return Filter{freq_tag<N>{}};
}
constexpr int get_i() const { return i; }
constexpr int get_j() const { return j; }
private:
int i;
int j;
};
int main() {
constexpr auto filter = Filter::create<2>();
static_assert(filter.get_i() == 3, "!");
}
It's mainly a matter of taste if compared to the switch-based solution, but for the fact that this one should work also in C++11.

C++ function argument safety

In a function that takes several arguments of the same type, how can we guarantee that the caller doesn't mess up the ordering?
For example
void allocate_things(int num_buffers, int pages_per_buffer, int default_value ...
and later
// uhmm.. lets see which was which uhh..
allocate_things(40,22,80,...
A typical solution is to put the parameters in a structure, with named fields.
AllocateParams p;
p.num_buffers = 1;
p.pages_per_buffer = 10;
p.default_value = 93;
allocate_things(p);
You don't have to use fields, of course. You can use member functions or whatever you like.
If you have a C++11 compiler, you could use user-defined literals in combination with user-defined types. Here is a naive approach:
struct num_buffers_t {
constexpr num_buffers_t(int n) : n(n) {} // constexpr constructor requires C++14
int n;
};
struct pages_per_buffer_t {
constexpr pages_per_buffer_t(int n) : n(n) {}
int n;
};
constexpr num_buffers_t operator"" _buffers(unsigned long long int n) {
return num_buffers_t(n);
}
constexpr pages_per_buffer_t operator"" _pages_per_buffer(unsigned long long int n) {
return pages_per_buffer_t(n);
}
void allocate_things(num_buffers_t num_buffers, pages_per_buffer_t pages_per_buffer) {
// do stuff...
}
template <typename S, typename T>
void allocate_things(S, T) = delete; // forbid calling with other types, eg. integer literals
int main() {
// now we see which is which ...
allocate_things(40_buffers, 22_pages_per_buffer);
// the following does not compile (see the 'deleted' function):
// allocate_things(40, 22);
// allocate_things(40, 22_pages_per_buffer);
// allocate_things(22_pages_per_buffer, 40_buffers);
}
Two good answers so far, one more: another approach would be to try leverage the type system wherever possible, and to create strong typedefs. For instance, using boost strong typedef (http://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/strong_typedef.html).
BOOST_STRONG_TYPEDEF(int , num_buffers);
BOOST_STRONG_TYPEDEF(int , num_pages);
void func(num_buffers b, num_pages p);
Calling func with arguments in the wrong order would now be a compile error.
A couple of notes on this. First, boost's strong typedef is rather dated in its approach; you can do much nicer things with variadic CRTP and avoid macros completely. Second, obviously this introduces some overhead as you often have to explicitly convert. So generally you don't want to overuse it. It's really nice for things that come up over and over again in your library. Not so good for things that come up as a one off. So for instance, if you are writing a GPS library, you should have a strong double typedef for distances in metres, a strong int64 typedef for time past epoch in nanoseconds, and so on.
(Note: post was originally tagged 'C`)
C99 onwards allows an extension to #Dietrich Epp idea: compound literal
struct things {
int num_buffers;
int pages_per_buffer;
int default_value
};
allocate_things(struct things);
// Use a compound literal
allocate_things((struct things){.default_value=80, .num_buffers=40, .pages_per_buffer=22});
Could even pass the address of the structure.
allocate_things(struct things *);
// Use a compound literal
allocate_things(&((struct things){.default_value=80,.num_buffers=40,.pages_per_buffer=22}));
You can't. That's why it is recommended to have as few function arguments as possible.
In your example you could have separate functions like set_num_buffers(int num_buffers), set_pages_per_buffer(int pages_per_buffer) etc.
You probably have noticed yourself that allocate_things is not a good name because it doesn't express what the function is actually doing. Especially I would not expect it to set a default value.
Just for completeness, you could use named arguments, when your call becomes.
void allocate_things(num_buffers=20, pages_per_buffer=40, default_value=20);
// or equivalently
void allocate_things(pages_per_buffer=40, default_value=20, num_buffers=20);
However, with the current C++ this requires quite a bit of code to be implemented (in the header file declaring allocate_things(), which must also declare appropriate external objects num_buffers etc providing operator= which return a unique suitable object).
---------- working example (for sergej)
#include <iostream>
struct a_t { int x=0; a_t(int i): x(i){} };
struct b_t { int x=0; b_t(int i): x(i){} };
struct c_t { int x=0; c_t(int i): x(i){} };
// implement using all possible permutations of the arguments.
// for many more argumentes better use a varidadic template.
void func(a_t a, b_t b, c_t c)
{ std::cout<<"a="<<a.x<<" b="<<b.x<<" c="<<c.x<<std::endl; }
inline void func(b_t b, c_t c, a_t a) { func(a,b,c); }
inline void func(c_t c, a_t a, b_t b) { func(a,b,c); }
inline void func(a_t a, c_t c, b_t b) { func(a,b,c); }
inline void func(c_t c, b_t b, a_t a) { func(a,b,c); }
inline void func(b_t b, a_t a, c_t c) { func(a,b,c); }
struct make_a { a_t operator=(int i) { return {i}; } } a;
struct make_b { b_t operator=(int i) { return {i}; } } b;
struct make_c { c_t operator=(int i) { return {i}; } } c;
int main()
{
func(b=2, c=10, a=42);
}
Are you really going to try to QA all the combinations of arbitrary integers? And throw in all the checks for negative/zero values etc?
Just create two enum types for minimum, medium and maximum number of buffers, and small medium and large buffer sizes. Then let the compiler do the work and let your QA folks take an afternoon off:
allocate_things(MINIMUM_BUFFER_CONFIGURATION, LARGE_BUFFER_SIZE, 42);
Then you only have to test a limited number of combinations and you'll have 100% coverage. The people working on your code 5 years from now will only need to know what they want to achieve and not have to guess the numbers they might need or which values have actually been tested in the field.
It does make the code slightly harder to extend, but it sounds like the parameters are for low-level performance tuning, so twiddling the values should not be perceived as cheap/trivial/not needing thorough testing. A code review of a change from
allocate_something(25, 25, 25);
...to
allocate_something(30, 80, 42);
...will likely get just a shrug/blown off, but a code review of a new enum value EXTRA_LARGE_BUFFERS will likely trigger all the right discussions about memory use, documentation, performance testing etc.

Boost: Vector of Distributions with any

Dear Stack Exchange Experts,
I am trying to set up a class (multivariate distribution function) that stores boost distributions in a std::vector (marginal distribution functions).
While this is possible using boost::variant (see my question: Boost: Store Pointers to Distributions in Vector), I also gave boost::any a try.
The reason being that with variant I have to hard-code the potential types (marginal distributions) when setting up the variant and I wanted to avoid this.
While the different implemented distribution classes do not share a common parent class, there are functions such as boost::math::cdf or boost::math::pdf that can be applied to all distributions, and that I want to apply iterating over the std::vector.
Working with any I produced the code below (which is running fine), but now I have the problem that the function any_cdf needs to check the types.
While I circumvented hard-coding the types when setting up the vector (as for variant) I now need to hard-code the types in the any_cdf function (while the solution with variants can handle the application of the cdf function via a templated visitor function, and thus without any type specifications) which means lots of code to manage, lots of if statements...
However, the logic does not change at all (I cast the type, then apply the cdf function in all if statements), and I wouldn't really care how the function behaves if something other than a boost distribution gets stored in the list.
So is there any chance to have my cake and eat it, meaning not being forced to hard-code the casting type of the distribution in any_cdf (much like a templated visitor function for variants)?
Thanks so much for your help, H.
P.s. if this is not feasible, would I generally be better of with boost::any or boost::variant in this situation?
#include <boost/math/distributions.hpp>
#include <boost/any.hpp>
#include <vector>
#include <iostream>
#include <limits>
//template function to apply cdf
template<class T> T any_cdf(boost::any a, T &x){
//declare return value
T y;
//cast any with hardcoded types
if (a.type() == typeid(boost::math::normal_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::normal_distribution<T> >(a),x);
} else if (a.type() == typeid(boost::math::students_t_distribution<T>)){
y = boost::math::cdf(boost::any_cast< boost::math::students_t_distribution<T> >(a), x);
} else {
//return NaN in case of failure or do something else (throw exception...)
y = std::numeric_limits<T>::quiet_NaN();
}
return(y);
}
int main (int, char*[])
{
//get distribution objects
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
//use any to put just any kind of objects in one vector
std::vector<boost::any> vec_any;
vec_any.push_back(s);
vec_any.push_back(t);
//evaluation point and return value
double y;
double x = 1.96;
for (std::vector<boost::any>::const_iterator iter = vec_any.begin(); iter != vec_any.end(); ++iter){
y = any_cdf<double>(*iter,x);
std::cout << y << std::endl;
}
return 0;
}
Edit: Concerning the comments any seems not to be the easiest/best choice for the task at hand. However for completeness reasons a visitor like implementation for boost::any is discussed at:
visitor pattern for boost::any
Note See my older answer for a discussion of solutions a vector and boost::any vs. boost::variant.
If you don't actually need a dynamic vector of distributions - but just want to apply a statically known list of distributions, you can "get away" with a tuple<> of them.
Now, with a bit (well, a lot) of magic from Phoenix and Fusion, you can "just" adapt the cdf function as a Lazy Actor:
BOOST_PHOENIX_ADAPT_FUNCTION(double, cdf_, boost::math::cdf, 2)
In which case an equivalent extended code sample shrinks to: See it Live On Coliru
int main()
{
typedef boost::tuple<bm::normal, bm::students_t> Dists;
Dists dists(bm::normal(), bm::students_t(1));
double x = 1.96;
boost::fusion::for_each(dists, std::cout << cdf_(arg1, x) << "\n");
std::cout << "\nComposite (multiplication):\t" << boost::fusion::accumulate(dists, 1.0, arg1 * cdf_(arg2, x));
std::cout << "\nComposite (mean):\t\t" << boost::fusion::accumulate(dists, 0.0, arg1 + cdf_(arg2, x)) / boost::tuples::length<Dists>::value;
}
Whoah. That's... hardly 6 lines of code :) And the best part is it's all c++03 compatible already.
Update This is the answer assuming a vector and boost::any vs. boost::variant. If you can use a tuple<> see my other answer
You will end up hardcoding the potential types one way or another.
With variant, you can group and hide the complexities by using visitor:
struct invoke_member_foo : boost::static_visitor<double>
{
template <typename Obj, typename... Args>
double operator()(Obj o, Args const&... a) const {
return o.foo(a...);
}
};
This can be applied to your variant like
boost::apply_visitor(invoke_member_foo(), my_variant);
With boost any, you'd do the typeswitching the boring and manual way:
if (auto dist1 = boost::any_cast<distribution1_t>(&my_any))
dist1->foo();
else if (auto dist2 = boost::any_cast<distribution2_t>(&my_any))
dist2->foo();
else if (auto dist3 = boost::any_cast<distribution3_t>(&my_any))
dist3->foo();
IMO this is clearly inferior for maintainability e.g.
you can't easily extend the type list with an element type that is similar enough to satisfy the same concept and have it support - you'll need to add cases to the type-switch manually (and if you don't - you're out of luck, there is no error and you'll have (silent) bugs. With variant you'll just get a compile error whenever your visitor doesn't handle your type.
this work ^ (the type switching) gets duplicated for each operation that you want to implement across the board. Of course, you can implement the type-switch once, and provide the actual implementation as a functor, but at that moment you'll have implemented the exact equivalent of a static_visitor as I showed for the variant, except with far less efficient implementation.
boost::any can only contain values that are CopyConstructible. Boost variant can even contain references (e.g. boost::variant<dist1_t&, dist2_t&>) and has (some) move-semantics support
In short, boost::any saves on time thought in advance, but all it does is shift the work to the call-sites.
On a positive note, let me share with you an idiom I like, which makes visitors accessible as ordinary free functions. Let's rewrite your any_cdf function for the variant:
namespace detail
{
template <typename T> struct var_cdf_visitor : boost::static_visitor<T> {
template <typename Dist>
T operator()(Dist& dist, T& x) const { return boost::math::cdf(dist, x); }
};
}
template<class T> T var_cdf(VarDist<T> a, T &x)
{
static detail::var_cdf_visitor<T> vis;
return boost::apply_visitor(
boost::bind(vis, ::_1, boost::ref(x)),
a);
}
A full running program can be found Live On Coliru
Demo Listing
#include <boost/bind.hpp>
#include <boost/math/distributions.hpp>
#include <boost/variant.hpp>
#include <iostream>
#include <limits>
#include <vector>
namespace detail
{
template <typename T> struct var_cdf_visitor : boost::static_visitor<T> {
template <typename Dist>
T operator()(Dist const& dist, T const& x) const { return boost::math::cdf(dist, x); }
};
}
template<class T, typename... Dist> T var_cdf(boost::variant<Dist...> const& a, T const& x) {
return boost::apply_visitor(boost::bind(detail::var_cdf_visitor<T>(), ::_1, x), a);
}
int main()
{
namespace bm = boost::math;
typedef std::vector<boost::variant<bm::normal, bm::students_t> > Vec;
Vec vec { bm::normal(), bm::students_t(1) };
//evaluation point and return value
double x = 1.96;
for (auto& dist : vec)
std::cout << var_cdf(dist,x) << std::endl;
}
Actually, though I used a bit of c++11, this could be made even prettier using some c++1y features (if your compiler has them).
And lastly, you can make work for c++03 too; it would just require more time than I currently have to throw at it.
What about:
int main (int, char*[])
{
boost::math::normal_distribution<double> s;
boost::math::students_t_distribution<double> t(1);
typedef std::vector<boost::function<double (double)> > vec_t;
vec_t vec_func;
vec_func.push_back(boost::bind(boost::math::cdf<double>, boost::ref(s), _1));
vec_func.push_back(boost::bind(boost::math::cdf<double>, boost::ref(t), _1));
//evaluation point and return value
double y;
double x = 1.96;
for (vec_t::const_iterator iter = vec_func.begin(); iter != vec_func.end(); ++iter){
y = (*iter)(x);
std::cout << y << std::endl;
}
return 0;
}
Binding argument to a function template can be tricky though.

C++ similar behavior to java.lang.Enum<E> [duplicate]

It is common knowledge that built-in enums in C++ are not typesafe.
I was wondering which classes implementing typesafe enums are used out there...
I myself use the following "bicycle", but it is somewhat verbose and limited:
typesafeenum.h:
struct TypesafeEnum
{
// Construction:
public:
TypesafeEnum(): id (next_id++), name("") {}
TypesafeEnum(const std::string& n): id(next_id++), name(n) {}
// Operations:
public:
bool operator == (const TypesafeEnum& right) const;
bool operator != (const TypesafeEnum& right) const;
bool operator < (const TypesafeEnum& right) const;
std::string to_string() const { return name; }
// Implementation:
private:
static int next_id;
int id;
std::string name;
};
typesafeenum.cpp:
int TypesafeEnum::next_id = 1;
bool TypesafeEnum::operator== (const TypesafeEnum& right) const
{ return id == right.id; }
bool TypesafeEnum::operator!= (const TypesafeEnum& right) const
{ return !operator== (right); }
bool TypesafeEnum::operator< (const TypesafeEnum& right) const
{ return id < right.id; }
Usage:
class Dialog
{
...
struct Result: public TypesafeEnum
{
static const Result CANCEL("Cancel");
static const Result OK("Ok");
};
Result doModal();
...
};
const Dialog::Result Dialog::Result::OK;
const Dialog::Result Dialog::Result::CANCEL;
Addition:
I think I should have been more specific about the requirements. I'll try to summarize them:
Priority 1: Setting an enum variable to an invalid value should be impossible (a compile-time error) with no exceptions.
Priority 2: Converting an enum value to/from an int should be possible with a single explicit function/method call.
Priority 3: As compact, elegant and convenient declaration and usage as possible
Priority 4: Converting enum values to and from strings.
Priority 5: (Nice to have) Possibility to iterate over enum values.
I'm currently playing around with the Boost.Enum proposal from the Boost Vault (filename enum_rev4.6.zip). Although it was never officially submitted for inclusion into Boost, it's useable as-is. (Documentation is lacking but is made up for by clear source code and good tests.)
Boost.Enum lets you declare an enum like this:
BOOST_ENUM_VALUES(Level, const char*,
(Abort)("unrecoverable problem")
(Error)("recoverable problem")
(Alert)("unexpected behavior")
(Info) ("expected behavior")
(Trace)("normal flow of execution")
(Debug)("detailed object state listings")
)
And have it automatically expand to this:
class Level : public boost::detail::enum_base<Level, string>
{
public:
enum domain
{
Abort,
Error,
Alert,
Info,
Trace,
Debug,
};
BOOST_STATIC_CONSTANT(index_type, size = 6);
Level() {}
Level(domain index) : boost::detail::enum_base<Level, string>(index) {}
typedef boost::optional<Level> optional;
static optional get_by_name(const char* str)
{
if(strcmp(str, "Abort") == 0) return optional(Abort);
if(strcmp(str, "Error") == 0) return optional(Error);
if(strcmp(str, "Alert") == 0) return optional(Alert);
if(strcmp(str, "Info") == 0) return optional(Info);
if(strcmp(str, "Trace") == 0) return optional(Trace);
if(strcmp(str, "Debug") == 0) return optional(Debug);
return optional();
}
private:
friend class boost::detail::enum_base<Level, string>;
static const char* names(domain index)
{
switch(index)
{
case Abort: return "Abort";
case Error: return "Error";
case Alert: return "Alert";
case Info: return "Info";
case Trace: return "Trace";
case Debug: return "Debug";
default: return NULL;
}
}
typedef boost::optional<value_type> optional_value;
static optional_value values(domain index)
{
switch(index)
{
case Abort: return optional_value("unrecoverable problem");
case Error: return optional_value("recoverable problem");
case Alert: return optional_value("unexpected behavior");
case Info: return optional_value("expected behavior");
case Trace: return optional_value("normal flow of execution");
case Debug: return optional_value("detailed object state listings");
default: return optional_value();
}
}
};
It satisfies all five of the priorities which you list.
A nice compromise method is this:
struct Flintstones {
enum E {
Fred,
Barney,
Wilma
};
};
Flintstones::E fred = Flintstones::Fred;
Flintstones::E barney = Flintstones::Barney;
It's not typesafe in the same sense that your version is, but the usage is nicer than standard enums, and you can still take advantage of integer conversion when you need it.
I use C++0x typesafe enums. I use some helper template/macros that provide the to/from string functionality.
enum class Result { Ok, Cancel};
I don't. Way too much overhead for little benefit. Also, being able to caste enumerations to different data types for serialization is a very handy tool. I have never seen an instance where a "Type safe" enumeration would be worth the overhead and complexity where C++ offers a good enough implementation already.
My take is that you're inventing a problem and then fitting a solution onto it. I see no need to do an elaborate framework for an enumeration of values. If you are dedicated to having your values only be members of a certain set, you could hack up a variant of a unique set datatype.
I'm personally using an adapted version of the typesafe enum idiom. It doesn't provide all the five "requirements" that you've stated in your edit, but I strongly disagree with some of them anyway. For example, I don't see how Prio#4 (conversion of values to strings) has anything to do with type safety. Most of the time string representation of individual values should be separate from the definition of the type anyway (think i18n for a simple reason why). Prio#5 (iteratio, which is optional) is one of the nicest things I'd like to see naturally happening in enums, so I felt sad that it appears as "optional" in your request, but it seems it is better addressed via a separate iteration system such as begin/end functions or an enum_iterator, which makes them work seamlessly with STL and C++11 foreach.
OTOH this simple idiom nicely provides Prio#3 Prio#1 thanks to the fact that it mostly only wraps enums with more type information. Not to mention it is a very simple solution that for the most part doesn't require any external dependency headers, so it's pretty easy to carry around. It also has the advantage of making enumerations scoped a-la-C++11:
// This doesn't compile, and if it did it wouldn't work anyway
enum colors { salmon, .... };
enum fishes { salmon, .... };
// This, however, works seamlessly.
struct colors_def { enum type { salmon, .... }; };
struct fishes_def { enum type { salmon, .... }; };
typedef typesafe_enum<colors_def> colors;
typedef typesafe_enum<fishes_def> fishes;
The only "hole" that solution provides is that it doesn't address the fact that it doesn't prevent enums of different types (or an enum and an int) from being directly compared, because when you use values directly you force the implicit conversion to int:
if (colors::salmon == fishes::salmon) { .../* Ooops! */... }
But so far I've found such problems can be solved by simply offering a better comparison to the compiler - for example, explicitly providing an operator that compares any two different enum types, then forcing it to fail:
// I'm using backports of C++11 utilities like static_assert and enable_if
template <typename Enum1, typename Enum2>
typename enable_if< (is_enum<Enum1>::value && is_enum<Enum2>::value) && (false == is_same<Enum1,Enum2>::value) , bool >
::type operator== (Enum1, Enum2) {
static_assert (false, "Comparing enumerations of different types!");
}
Though it doesn't seem to break code so far, and it does to explicitly deal with the specific problem without doing something else, I'm not sure it such thing is a thing one "should" do (I suspect it will interfere with enums already taking part in conversion operators declared elsewhere; I'd gladly receive commentary about this).
Combining this with the above typesafe idiom gives something that is relatively close to C++11 enum class in humanibility (readability and maintainability) without having to do anything too obscure. And I have to admit it was fun to do, I had never thought to actually ask the compiler if I was dealing with enums or not...
I think the Java enum would be a good model to follow. Essentially, the Java form would look like this:
public enum Result {
OK("OK"), CANCEL("Cancel");
private final String name;
Result(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
What's interesting about the Java approach is that OK and CANCEL are immutable, singleton instances of Result (with the methods that you see). You cannot create any further instances of Result. Since they're singletons, you can compare by pointer/reference---very handy. :-)
ETA: In Java, instead of doing bitmasks by hand, instead you use an EnumSet to specify a bit set (it implements the Set interface, and works like sets---but implemented using bitmasks). Much more readable than hand-written bitmask manipulation!
I gave an answer to this here, on a different topic. It's a different style of approach which allows most of the same functionality without requiring modification to the original enum definition (and consequently allowing usage in cases where you don't define the enum). It also allows runtime range checking.
The downside of my approach is that it doesn't programmatically enforce the coupling between the enum and the helper class, so they have to be updated in parallel. It works for me, but YMMV.
I am currently writing my own typesafe enum library at https://bitbucket.org/chopsii/typesafe-enums
I am not the most experienced C++ developer ever, but I am writing this due to the shortcomings of the BOOST vault enums.
Feel free to check it out and use them yourself, but they have some (hopefully minor) usability issues, and are probably not at all cross-platform.
Please contribute if you want to. This is my first open source undertaking.
Use boost::variant!
After trying a lot of the above ideas and finding them lacking I hit upon this simple approach:
#include <iostream>
#include <boost/variant.hpp>
struct A_t {};
static const A_t A = A_t();
template <typename T>
bool isA(const T & x) { if(boost::get<A_t>(&x)) return true; return false; }
struct B_t {};
static const B_t B = B_t();
template <typename T>
bool isB(const T & x) { if(boost::get<B_t>(&x)) return true; return false; }
struct C_t {};
static const C_t C = C_t();
template <typename T>
bool isC(const T & x) { if(boost::get<C_t>(&x)) return true; return false; }
typedef boost::variant<A_t, B_t> AB;
typedef boost::variant<B_t, C_t> BC;
void ab(const AB & e)
{
if(isA(e))
std::cerr << "A!" << std::endl;
if(isB(e))
std::cerr << "B!" << std::endl;
// ERROR:
// if(isC(e))
// std::cerr << "C!" << std::endl;
// ERROR:
// if(e == 0)
// std::cerr << "B!" << std::endl;
}
void bc(const BC & e)
{
// ERROR:
// if(isA(e))
// std::cerr << "A!" << std::endl;
if(isB(e))
std::cerr << "B!" << std::endl;
if(isC(e))
std::cerr << "C!" << std::endl;
}
int main() {
AB a;
a = A;
AB b;
b = B;
ab(a);
ab(b);
ab(A);
ab(B);
// ab(C); // ERROR
// bc(A); // ERROR
bc(B);
bc(C);
}
You can probably come up with a macro to generate the boilerplate. (Let me know if you do.)
Unlike other approaches this one is actually type-safe and works with old C++. You can even make cool types like boost::variant<int, A_t, B_t, boost::none>, for example, to represent a value that could be A, B, an integer or nothing which is almost Haskell98 levels of type safety.
Downsides to be aware of:
at-least with old boost -- I'm on a system with boost 1.33 -- you are limited to 20 items in your variant; there is a work-around however
affects compile time
insane error messages -- but that's C++ for you
Update
Here, for your convenience is your typesafe-enum "library". Paste this header:
#ifndef _TYPESAFE_ENUMS_H
#define _TYPESAFE_ENUMS_H
#include <string>
#include <boost/variant.hpp>
#define ITEM(NAME, VAL) \
struct NAME##_t { \
std::string toStr() const { return std::string( #NAME ); } \
int toInt() const { return VAL; } \
}; \
static const NAME##_t NAME = NAME##_t(); \
template <typename T> \
bool is##NAME(const T & x) { if(boost::get<NAME##_t>(&x)) return true; return false; } \
class toStr_visitor: public boost::static_visitor<std::string> {
public:
template<typename T>
std::string operator()(const T & a) const {
return a.toStr();
}
};
template<BOOST_VARIANT_ENUM_PARAMS(typename T)>
inline static
std::string toStr(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & a) {
return boost::apply_visitor(toStr_visitor(), a);
}
class toInt_visitor: public boost::static_visitor<int> {
public:
template<typename T>
int operator()(const T & a) const {
return a.toInt();
}
};
template<BOOST_VARIANT_ENUM_PARAMS(typename T)>
inline static
int toInt(const boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> & a) {
return boost::apply_visitor(toInt_visitor(), a);
}
#define ENUM(...) \
typedef boost::variant<__VA_ARGS__>
#endif
And use it like:
ITEM(A, 0);
ITEM(B, 1);
ITEM(C, 2);
ENUM(A_t, B_t) AB;
ENUM(B_t, C_t) BC;
Notice you have to say A_t instead of A in the ENUM macro which destroys some of the magic. Oh well. Also, notice there's now a toStr function and a toInt function to meet OPs requirement of simple conversion to strings and ints. The requirement I can't figure out is a way to iterate over the items. Let me know if you know how to write such a thing.
Not sure if this post is too late, but there's an article on GameDev.net which satisfies all but the 5th point (ability to iterate over enumerators):
http://www.gamedev.net/reference/snippets/features/cppstringizing/
The method described by the article allows string conversion support for existing enumerations without changing their code. If you only want support for new enumerations though, I'd go with Boost.Enum (mentioned above).