Idiom for a C++11 enum with methods and static instances? - c++

I'd like to do the following (which won't compile):
class Foo {
int value;
Foo(const int arg)
: value{arg}
{}
public:
static const Foo a{0};
static const Foo b{1};
static const Foo c{2};
Foo func(const Foo& foo) {...}
};
so that the the instances of Foo are strongly controlled (like in an enum) and so that I can write code like auto foo = Foo::a; and auto foo = Foo::a.func(Foo::b);
Unfortunately, the code won't compile under C++11 because the static instances have incomplete type.
Is there an idiom for this?

You can do it quite easily but you need to put the definitions of your constants outside the class:
class Foo {
int value;
// In C++17, you could make this constexpr.
Foo(const int arg)
: value{arg}
{}
public:
// in C++20, you could make these constinit.
static const Foo a;
static const Foo b;
static const Foo c;
};
// In C++11 these need to go in the source file to avoid linker errors.
// In C++17 you could make them inline and put them in the header.
// In C++20 you could make them constinit.
const Foo Foo::a = 0;
const Foo Foo::b = 1;
const Foo Foo::c = 2;
I wouldn't call this an elegant solution though. Particularly in C++11, these constants can't be inlined by the compiler because they need to go into the source file. This can have a significant impact on performance. So if you're going to do it, I would recommend using at least C++17, if not C++20.
Generally, C++ enums are meant to be integer constants and there is no support for getting the ordinal or name of an enum like there is in Java. An alternative approach is to use an enum class with no values (which defaults to values 0, 1, 2, ...) and then use them as indices inside of lookup tables.
Using a switch for properties can also do the trick:
enum class Axis : unsigned { X, Y, Z };
// in C++17, you could make this constexpr.
inline const char *nameOf(Axis axis)
{
switch (axis) {
case Axis::X: return "X";
case Axis::Y: return "Y";
case Axis::Z: return "Z";
}
}

Related

How to make const variables filled at runtime accessible across all of the program?

What technique should I use to make a list of const variables whose value is known only at runtime accessible across all of the program?
Yes, I can make it in a way like that:
class some
{
static const int a;
static const int b;
...
static const int z;
};
int some::a(f1());
int some::b(f2());
...
int some::z(f3());
And I guess it will work fine... But what if there are many such variables? In such a case there must be a lot of corresponding functions, and I don't find this solution elegant.
Have you got any ideas?
I know many won't like this, because Singletons are considered bad design, anti patterns and whatnot. Though Singletons are ubiquituous in many framework and architectural designs.
That said, now for the OPs question:
But what if there are many such variables? In such a case there must be a lot of corresponding functions, and I don't find this solution elegant.
First of all you shouldn't stray these values over the global space (even not if appearing in a struct).
What you can do instead:
class MyConfiguration {
public:
static const MyConfiguration& instance() {
static MyConfiguration theInstance;
return theInstance;
}
int a() const { return a_; }
int b() const { return b_; }
int c() const { return c_; }
private:
MyConfiguration() : a_(0), b_(0), c_(0) {
loadConfigValues();
}
void loadConfigValues() {
a_ = 42;
b_ = getFromElseWhere();
c_ = a_ * b_;
}
int a_;
int b_;
int c_;
};
Your constants will be loaded once, and are accessible using
int y = MyConfiguration::instance().a();
int bar = MyConfiguration::instance().b();
You'll still need a lot of getter functions this way, but it's better maintainable, and guaranteed to be used only from one access point.
Just before someone comes mentioning the "static initialization order fiasco" or thread safety of instantiation, the above implementation overcomes these problems.
For the second part, you can use an array:
std::array<int> params;
or
std::array<std::any> params
if they are of different type. I'm assuming you want to have an uniform interface.
As for the scope, making the list global or making it a singleton would certainly work, but you gotta be very very careful. If you have many functions using those variables, perhaps wrapping them in a class would be appropriate.
As others suggested using singleton is a grand solution for your problem. But if you need a simpler one and if only managing large number of uniform constants and functions is what you are after you can use it inside templates like this:
template<long number>
int const_filler(int v){
return number * v;
};
template<long number>
struct const_holder{
static const long value;
};
template<long number>
const int const_holder<number>::value = const_filler< number>(2);
int main()
{
std::cout << const_holder<2>::value << std::endl;
return 0;
}
Now the constants are
const_holder<0>::value
const_holder<1>::value
const_holder<2>::value
.
.
.
And they are filled at the first usage.
With this method you can have as many (actually as many as long integers that processor supports) constants and functions as you want. if you want a version which you can also choose the type of the constant then you can use the following:
template<typename type, long number>
type const_filler(int v){
return number * v;
};
template<typename type, long number>
struct const_holder{
static const type value;
};
template<typename type, long number>
const type const_holder<type, number>::value = const_filler<type, number>(2);
int main()
{
std::cout << const_holder<int, 2>::value << std::endl;
return 0;
}

c++ method as template argument

I am trying to specialize std::unordered_map for a class X with a custom hash and a custom equality. The problem is that both the equality and hash functions do not depend only on the object(s) of class X but also on data in another (fixed) object of another class Y. Here is a toy example (with only the hash function) of what I want to do:
#include <unordered_map>
using namespace std;
struct Y {
bool b;
struct X {
size_t i;
};
size_t hash(const X &x) {
return x.i + b;
}
unordered_map<X, int, hash> mymap;
};
The problem is that the function hash in the template specialization is a method and the compiler complains ("call to non-static member function without an object argument"). What I want is that y.mymap uses y.hash(). Any way to do this?
Note that in the real code Y is also a template, in case it matters.
Thanks!
EDIT: To clarify, instead of the boolean b in my code I have a vector with data that is needed in comparing objects of type X. Some data is added when an X is created, so the vector is not constant, but the data for a given X does not change after it is added, so the hash for a given X never changes (so in a sense it depends only on X as required for a hash). The main reason I use this approach is to save memory since this data is a lot and is usually shared.
You can use function<size_t(X const&)> and e.g. bind, but as type erasure is not necessary in this case, here is a simpler solution:
struct Y {
bool b;
struct X {
size_t i;
bool operator==(X x) const {return i == x.i;}
};
size_t hash(const X &x) {
return x.i + b;
}
struct Hasher {
Y* this_;
template <typename T>
auto operator()(T&& t) const
-> decltype(this_->hash(std::forward<T>(t))) {
return this_->hash(std::forward<T>(t));
}
};
unordered_map<X, int, Hasher> mymap;
Y() : b(false),
mymap(0, {this}) {}
};
As mentioned by #dyp in the comments, you have to be careful with special member functions since we implicitly store this in mymap - i.e. the compiler-generated definitions would copy the this_ pointer. An example implementation of the move constructor could be
Y(Y&& y) : b(y.b), mymap(std::make_move_iterator(std::begin(y.mymap)),
std::make_move_iterator(std::end (y.mymap)), 0, {this}) {}
Unfortunately what you want to do is not legal. See 17.6.3.5/Table 26:
h(k) The value returned shall depend only on the argument k.
It's pretty clear that you aren't allowed to have the hash depend on a member of Y as well as X.
EDIT: Just in case you meant for b to be const in your Y class there is a solution (I didn't compile this yet, I will if I get a chance):
struct Y
{
explicit Y(bool config) : b(config), hash_(config), mymap(0, hash_) { }
const bool b;
struct X
{
size_t i;
};
struct Hash
{
explicit Hash(bool b) : b_(b) { }
size_t operator()(const X& x) const
{
return x.i + b_;
}
private:
bool b_;
};
Hash hash_;
unordered_map<X, int, Hash> mymap;
};

Compile-Time Named Parameter Idiom with constexpr

I've recently run into a quite a few situations where the Named Parameter Idiom would be useful, but I'd like it to be guaranteed in compile-time. The standard method of returning references in a chain almost always appears to invoke a run-time constructor (compiling with Clang 3.3 -O3).
I haven't been able to find anything with reference to this so I tried to get this to work with constexpr and got something functional:
class Foo
{
private:
int _a;
int _b;
public:
constexpr Foo()
: _a(0), _b(0)
{}
constexpr Foo(int a, int b)
: _a(a), _b(b)
{}
constexpr Foo(const Foo & other)
: _a(other._a), _b(other._b)
{}
constexpr Foo SetA(const int a) { return Foo(a, _b); }
constexpr Foo SetB(const int b) { return Foo(_a, b); }
};
...
Foo someInstance = Foo().SetB(5).SetA(2); //works
While this is okay for a small number of parameters, for larger numbers it quickly blows up into a mess:
//Unlike Foo, Bar takes 4 parameters...
constexpr Bar SetA(const int a) { return Bar(a, _b, _c, _d); }
constexpr Bar SetB(const int b) { return Bar(_a, b, _c, _d); }
constexpr Bar SetC(const int c) { return Bar(_a, _b, c, _d); }
constexpr Bar SetD(const int d) { return Bar(_a, _b, _c, d); }
Is there a better way? I'm looking at doing this with classes that have many (30+) parameters and this seems like it would be prone to error if extended in the future.
EDIT: Removed C++1y tag -- while C++1y does appear to fix the problem (thanks TemplateRex!) this is for production code, and we are stuck with C++11. If that means its impossible, then I guess that's just the way it is.
EDIT2: To show why I'm looking for this, here's a use case. Currently with our platform, developers need to explicitly set bit vectors for hardware configurations, and while this is okay it's very error prone. Some are using designated initializers from the C99 extension, which is okay but non-standard:
HardwareConfiguration hardwareConfig = {
.portA = HardwareConfiguration::Default,
.portB = 0x55,
...
};
Most, however, aren't even using this, and are just inputting a blob of numbers. So as a working improvement, I'd like to move towards something like this (since it also forces better code):
HardwareConfiguration hardwareConfig = HardwareConfiguration()
.SetPortA( Port().SetPolarity(Polarity::ActiveHigh) )
.SetPortB( Port().SetPolarity(Polarity::ActiveLow) );
Which might be far more verbose, but much clearer when reading later.
Using Template Metaprogramming
Here is something I came up with to solve your problem (at least partially). By using template metaprogramming, you can leverage the compiler to do most of the job for you. These techniques look weird for those who have never seen such code before, but thankfully most of the complexity can be hidden away in a header and the users only interact with the library in a neat and terse manner.
A Sample Class Definition and its Use
Here is an example of what defining a class would entail on your part:
template <
//Declare your fields here, with types and default values
typename PortNumber = field<int, 100>,
typename PortLetter = field<char, 'A'>
>
struct MyStruct : public const_obj<MyStruct, PortNumber, PortLetter> //Derive from const_obj like this, passing the name of your class + all field names as parameters
{
//Your setters have to be declared like this, by calling the Set<> template provided by the base class
//The compiler needs to be told that Set is part of MyStruct, probably because const_obj has not been instantiated at this point
//in the parsing so it doesn't know what members it has. The result is that you have to use the weird 'typename MyStruct::template Set<>' syntax
//You need to provide the 0-based index of the field that holds the corresponding value
template<int portNumber>
using SetPortNumber = typename MyStruct::template Set<0, portNumber>;
template<int portLetter>
using SetPortLetter = typename MyStruct::template Set<1, portLetter>;
template<int portNumber, char portLetter>
using SetPort = typename MyStruct::template Set<0, portNumber>
::MyStruct::template Set<1, portLetter>;
//You getters, if you want them, can be declared like this
constexpr int GetPortNumber() const
{
return MyStruct::template Get<0>();
}
constexpr char GetPortLetter() const
{
return MyStruct::template Get<1>();
}
};
Using the Class
int main()
{
//Compile-time generation of the type
constexpr auto myObject =
MyStruct<>
::SetPortNumber<150>
::SetPortLetter<'Z'>();
cout << myObject.GetPortNumber() << endl;
cout << myObject.GetPortLetter() << endl;
}
Most of the job is done by the const_obj template. It provides a mechanism to modify your object at compile time. Much like a Tuple, the fields are accessed with 0-based indices but this does not stop you from wrapping the setters with friendly names, as is done with SetPortNumber and SetPortLetter above. (They just forward to Set<0> and Set<1>)
About Storage
In the current implementation, after all the setters have been called and the object declared, the fields end up being stored in a compact array of const unsigned char's named data in the base class. If you use fields that are not unsigned chars (as in done above with PortNumber for example) the field is divided in big endien unsigned char's (could be changed to little endien as needed). If you don't need an actual storage that has an actual memory address, you could omit it altogether by modifying the packed_storage (see full implementation link below) and the values would still be accessible at compile time.
Limitations
This implementation only allows integral types to be used as fields (all flavors of shorts, ints, longs, bool, char). You can still provide setters that act on more than one field though. Example:
template<int portNumber, char portLetter>
using SetPort = typename MyStruct::template Set<0, portNumber>::
MyStruct::template Set<1, portLetter>;
Full Code
The full code for the implementation of this little library can be found here:
Full Implementation
Additional Notes
This code has been tested and works with the C++11 implementation of both g++ and clang.
It has not been tested for hours and hours so of course there may be bugs but it should provide you with a good base to start with. I hope this helps!
In C++14, constraints on constexpr function will be relaxed, and the usual chaining of reference-returning setters will work at compile-time:
#include <iostream>
#include <iterator>
#include <array>
#include <utility>
class Foo
{
private:
int a_ = 0;
int b_ = 0;
int c_ = 0;
int d_ = 0;
public:
constexpr Foo() = default;
constexpr Foo(int a, int b, int c, int d)
:
a_{a}, b_{b}, c_{c}, d_{d}
{}
constexpr Foo& SetA(int i) { a_ = i; return *this; }
constexpr Foo& SetB(int i) { b_ = i; return *this; }
constexpr Foo& SetC(int i) { c_ = i; return *this; }
constexpr Foo& SetD(int i) { d_ = i; return *this; }
friend std::ostream& operator<<(std::ostream& os, const Foo& f)
{
return os << f.a_ << " " << f.b_ << " " << f.c_ << " " << f.d_ << " ";
}
};
int main()
{
constexpr Foo f = Foo{}.SetB(5).SetA(2);
std::cout << f;
}
Live Example using Clang 3.4 SVN trunk with std=c++1y.
I'm not sure if classes with 30 parameters are a good idea (Single Responsiblity Principle and all that) but at least the above code scales linearly in the number of setters, with only 1 argument per setter. Note also that there are only 2 constructors: the default one (which takes its arguments from the in-class initializers) and the full one which takes 30 ints in your ultimate case).

Deriving different and incomparable types from int in C++

I know I cannot derive from an int and it is not even necessary, that was just one (non)solution that came to my mind for the problem below.
I have a pair (foo,bar) both of which are represented internally by an int but I want the typeof(foo) to be incomparable with the typeof(bar). This is mainly to prevent me from passing (foo,bar) to a function that expects (bar, foo). If I understand it correctly, typedef will not do this as it is only an alias. What would be the easiest way to do this. If I were to create two different classes for foo and bar it would be tedious to explicitly provide all the operators supported by int. I want to avoid that.
As an alternative to writing it yourself, you can use BOOST_STRONG_TYPEDEF macro available in boost/strong_typedef.hpp header.
// macro used to implement a strong typedef. strong typedef
// guarentees that two types are distinguised even though the
// share the same underlying implementation. typedef does not create
// a new type. BOOST_STRONG_TYPEDEF(T, D) creates a new type named D
// that operates as a type T.
So, e.g.
BOOST_STRONG_TYPEDEF(int, foo)
BOOST_STRONG_TYPEDEF(int, bar)
template <class Tag>
class Int
{
int i;
public:
Int(int i):i(i){} //implicit conversion from int
int value() const {return i;}
operator int() const {return i;} //implicit convertion to int
};
class foo_tag{};
class bar_tag{};
typedef Int<foo_tag> Foo;
typedef Int<bar_tag> Bar;
void f(Foo x, Bar y) {...}
int main()
{
Foo x = 4;
Bar y = 10;
f(x, y); // OK
f(y, x); // Error
}
You are correct, that you cannot do it with typedef. However, you can wrap them in a struct-enum pair or int encapsuled inside struct.
template<int N>
struct StrongType { // pseudo code
int i;
StrongType () {}
StrongType (const int i_) : i(i_) {}
operator int& () { return i; }
StrongType& operator = (const int i_) {
i = i_;
return *this;
}
//...
};
typedef StrongType<1> foo;
typedef StrontType<2> bar;
C++0x solution:
enum class foo {};
enum class bar {};

Why do people use enums in C++ as constants while they can use const?

Why do people use enums in C++ as constants when they can use const?
Bruce Eckel gives a reason in Thinking in C++:
In older versions of C++, static const was not supported inside classes. This meant that const was useless for constant expressions inside classes. However, people still wanted to do this so a typical solution (usually referred to as the “enum hack”) was to use an untagged enum with no instances. An enumeration must have all its values established at compile time, it’s local to the class, and its values are available for constant expressions. Thus, you will commonly see:
#include <iostream>
using namespace std;
class Bunch {
enum { size = 1000 };
int i[size];
};
int main() {
cout << "sizeof(Bunch) = " << sizeof(Bunch)
<< ", sizeof(i[1000]) = "
<< sizeof(int[1000]) << endl;
}
Enums are distinct types, so you can do type-oriented things like overloading with them:
enum Color { Red,Green,Blue };
enum Size { Big,Little };
void f( Color c ) {
}
void f( Size s ) {
}
int main() {
f( Red );
f( Big );
}
An enumeration implies a set of related constants, so the added information about the relationship must be useful in their model of the problem at hand.
There's a historical reason too when dealing with template metaprogramming. Some compilers could use values from an enum, but not a static const int to instantiate a class.
template <int N>
struct foo
{
enum { Value = foo<N-1>::Value + N };
};
template <>
struct foo<0>
{
enum { Value = 0; }
};
Now you can do it the more sensible way:
template <int N>
struct foo
{
static const int Value = foo<N-1>::Value + N;
};
template <>
struct foo<0>
{
static const int Value = 0;
};
Another possible reason, is that a static const int may have memory reserved for it at runtime, whereas an enum is never going to have an actual memory location reserved for it, and will be dealt at compile time. See this related question.
Enums are more descriptive when used. Consider:
int f(int fg, int bg)
versus
int f(COLOR fg, COLOR bg)
In addition, enums give a bit more type-safety, because
integers are not implicitly convertible to enum types
enum of one type is not implicitly convertible to enum of another type
I like the automatic behavior that can be used with enums, for example:
enum {NONE, START, HEY, HO, LAST};
Then it is easy to loop until LAST, and when a new state (or whatever is represented) is added, the logic adapts.
for (int i = NONE; i < LAST; i++)
{
// Do stuff...
}
Add something...
enum {NONE, START, HEY, WEE, HO, LAST};
The loop adapts...
Before compiler vendors implemented the ISO/IEC 14882:1998 C++ standard, this code to define a constant in a class scope resulted in a compile error:
class Foo {
static const int MAX_LEN = 80;
...
};
If the constant is an integer type, a kludgy work around is define it in an enum inside the class:
class Foo {
enum {
MAX_LEN = 80
};
...
};
enums also can be used as a type name. So you can define a function that takes an enum as a parameter, which makes it more clear what kinds of values should be given as arguments to the function, as compared to having the values defined as const variables and the function accepting just "int" as an argument.
Consider:
enum my_new_fangled_type {
baz = 0,
meh = 1
};
void foo (my_new_fangled_type bar) // bar can be a value listed in the enum
{
...
}
versus:
int const baz = 0;
int const meh = 1;
void foo (int bar) // what are valid values for bar?
{
...
}
Some debuggers will show the enumeration name instead of its value when debugging. This can be very helpful. I know that I would rather see day_of_week = MONDAY than day_of_week = 1.
It's partly because older compilers did not support the declaration of a true class constant
class C
{
const int ARealConstant = 10;
};
so had to do this
class C
{
enum { ARealConstant = 10 };
};
For this reason, many portable libraries continue to use this form.
The other reason is that enums can be used as a convenient syntactic device to organise class constants into those that are related, and those that are not
class DirectorySearcher
{
enum options
{
showFiles = 0x01,
showDirectories = 0x02,
showLinks = 0x04,
};
};
vs
class Integer
{
enum { treatAsNumeric = true };
enum { treatAsIntegral = true };
enum { treatAsString = false };
};
Using an enum documents the valid choices in a terse manner and allows the compiler to enforce them.
If they are using enum store global constants, like Pi, for example, then I don't know what their goal is.
One reason is that const requires more typing:
enum { Val1, Val2, Val3 };
...versus...
const int Val1=0, Val2=1, Val3=2;