Applying a rule on how to increment an enum - c++

Is there a way to change how an enum sets the values of its constants? Normally it's incrementing by one but I want to apply an other rule. In PAWN this would work
enum (<<=1) {
a = 1,//0b001
b,//0b010
c//0b100
}
Is there a way to do this in C++?

not automatically, but you can specify manually each value
enum X {
a = 0x01,
b = 0x02,
c = 0x04
};

You could automate this shifting process using templates metaprogramming:
template<int by>
struct OneShlBy {
enum { Value = OneShlBy<by - 1>::Value << 1 };
};
template<>
struct OneShlBy<0> {
enum { Value = 1 };
};
enum X {
a = OneShlBy<0>::Value,
b = OneShlBy<1>::Value,
c = OneShlBy<2>::Value
};

One way, assuming C++11, would be
constexpr int func(int x)
{
return x << 1;
}
enum X
{
a = 1,
b = func(a),
c = func(b)
};
The func() can then be used to implement any relationship you like between consecutive named values.
Before C++11, alternatives might include
enum X
{
a = 1,
b = a << 1,
c = b << 1
};
or (with a macro)
#define func(x) x << 1
enum X
{
a = 1,
b = func(a),
c = func(b)
};
#undef func

One common approach for the particular example you give (enums which are essentially flags within a word) is to use two enums, one for the bit index and a second enum for the actual bit values:
enum {
b_a, // 0
b_b, // 1
b_c, // 2
b_d, // 3
};
enum {
a = 1 << b_a, // 1
b = 1 << b_b, // 2
c = 1 << b_c // 4
d = 1 << b_d // 8
};
It's not ideal, I know, but it avoids explicit literal constants. Some of the nastiness can be hidden with macros, which you may or may not consider a good thing to do.

What you were doing works perfectly fine:
#include <iostream>
enum x {
a = 0b001
, b = 0b010
, c = 0b100
};
int main()
{
std::cout << x::a << '\n';
std::cout << x::b << '\n';
std::cout << x::c << '\n';
}
Note: this is only standard in C++14 where binary literals are introduced.
Otherwise you can use the shift operator to specify the bit position:
enum x {
a = 1 << 0
, b = 1 << 1
, c = 1 << 2
};
Another possibility if you are looking to save some maintenance work is defining each enum in terms of previously defined enums:
enum x {
a = 1
, b = a << 1
, c = b << 1
, d = c << 1
, e = d << 1
};
This means you can add an element in the middle relatively painlessly:
enum x {
a = 1
, b = a << 1
, z = b << 1 // new element added
, c = z << 1 // only need to adjust one other
, d = c << 1
, e = d << 1
};

Stealing the great idea of Rob, there's a way to specify how to increment the value of an enum, this it isn't very automatic though, but as long as your enum have always the same fields you can do something like this:
template <typename T, T(*INC)(const T), T start = {}>
struct managed_enum
{
enum
{
a = start,
b = INC(a),
c = INC(b),
};
};
With this template you could do the following:
template<typename T>
constexpr T shift_left(const T value) { return value << 1; }
using shifted = managed_enum<int, shift_left<int>, 1>;
Which results on the enum you're looking for (see here). Well, shifted isnt an enum but a struct, hope it doesn't matters.
Defining different increment functions, you can have different families of enums automatically increased, as long as all of them have only the three values of managed_enum (a, b, c):
template<typename T>
constexpr T shift_left(const T value) { return value << 1; }
template<typename T>
constexpr T increment(const T value) { return value + 1; }
template<typename T>
constexpr T bicrement(const T value) { return value + 2; }
using shifted = managed_enum<int, shift_left<int>, 1>;
using increment = managed_enum<int, increment<int>>;
using bicrement = managed_enum<int, bicrement<int>>;

Related

Best C++ STL way to map ranges to values?

Want to know the most efficient way to map ranges of values in C++
When for example:
I have a bunch of objects differentiated by integer key ranges, e.g.
0-10 -> object a
11-20 -> object b
21-30 -> object c
Where objects are a particular class with a few variables of their own inside. There should be a thousand objects in this scenario.
I was wondering what is the best/fastest way in C++ STL to lookup an object based on an input key. e.g.
lookup(13) -> object b
Note that the ranges are not fixed and may not be of equal size.
Thanks
Easily accomplished with std::map and it's upper_bound function.
Use the lower end of each range as the key into a map. The corresponding value of the map type is a triple of {lower bound, upper bound, and item}. Then to lookup an object based on a specific value, invoke map::upper_bound and to find the the item in the map that is "one past" the matching item. Then "go back 1" and test to see if it's a match.
#include <algorithm>
#include <iostream>
#include <map>
template <typename T>
struct RangeAndValue
{
int low;
int high;
T value;
};
template <typename T>
struct RangeTable
{
std::map<int, RangeAndValue<T>> table;
void Insert(int low, int high, const T& t)
{
table[low] = {low, high, t};
}
bool Lookup(int value, T& t)
{
auto itor = table.upper_bound(value);
if (itor != table.begin())
{
itor--;
if ((value >= itor->second.low) && (value <= itor->second.high))
{
t = itor->second.value;
return true;
}
}
return false;
}
};
Proof of concept (using your sample ranges of 0-10 maps to a, 11-20 maps to b, and 21-30 maps to c)
int main()
{
RangeTable<std::string> rangeTable;
rangeTable.Insert(0, 10, "a");
rangeTable.Insert(11,20, "b");
rangeTable.Insert(21,30, "c");
for (int i = -1; i < 32; i++)
{
std::string s;
bool result = rangeTable.Lookup(i, s);
std::cout << i << " : " << (result ? s : "<not found>") << std::endl;
}
return 0;
}
Produces expected results when run:
$ g++ main.cpp -o testapp
$ ./testapp
-1 : <not found>
0 : a
1 : a
2 : a
3 : a
4 : a
5 : a
6 : a
7 : a
8 : a
9 : a
10 : a
11 : b
12 : b
13 : b
14 : b
15 : b
16 : b
17 : b
18 : b
19 : b
20 : b
21 : c
22 : c
23 : c
24 : c
25 : c
26 : c
27 : c
28 : c
29 : c
30 : c
31 : <not found>
Same idea as #selbie's answer, but using a transparent comparator to avoid wrapping the map in your own class:
#include <compare>
#include <iostream>
#include <map>
#include <string>
template <typename T>
struct Range
{
T begin{}, end{};
friend constexpr auto operator<=>(const Range &, const Range &) = default;
friend constexpr std::weak_ordering operator<=>(const Range &a, T b)
{
if (b < a.begin)
return std::weak_ordering::greater;
else if (b > a.end)
return std::weak_ordering::less;
else
return std::weak_ordering::equivalent;
}
};
int main()
{
std::map<Range<int>, std::string, std::less<>> m = {
{{0, 5}, "A"},
{{6, 10}, "B"},
{{11, 15}, "C"},
};
auto check = [&](int n)
{
auto it = m.find(n);
if (it != m.end())
std::cout << n << " -> " << it->second << '\n';
else
std::cout << n << " not in the map\n";
};
check(0); // A
check(1); // A
check(5); // A
check(6); // B
check(-1); // not in the map
check(16); // not in the map
}
First, we use std::less<> (without the template argument - the transparent version), which makes .find() a template, accepting any type comparable with the key type.
Next we make a range class that overloads comparison operators (using C++20) with itself and with its element type.
You could do the same thing with std::pair and with a custom transparent comparator (add using is_transparent = void;) that compares it with the numbers in the correct way.

Metaprogramming - power-like function

I want to define template which would behave similar to power function a^n
a^n = -1 where a < 0 or n < 0
a^0 = 0 (so not exactly as std::pow)
otherwise std::pow
I have a problem defining the condition for point 1 - I assume this will be a combination of enable_if and some defined constexpr checking whether integer is negative.
What I wrote for the 1. point (commented out below) probably does not make sense as it do not compile. I am only starting with metaprogramming, to be honest I do not quite understand it. I would much appreciate if you could provide explanation and/or some resources you found helpful while getting into the topic.
#include <iostream>
#include <cmath>
// std::pow
template <int a, int n>
struct hc {
enum { v = a * hc<a, n - 1>::v };
};
// to break recursion from getting to a^0=0
template <int a>
struct hc<a, 1> {
enum { v = a };
};
// a^0 = 0
template <int a>
struct hc<a, 0> {
enum { v = 0 };
};
// a^n=-1 for negative a or n
/*
template <int i>
constexpr bool is_negative = i < 0;
// a ^ n = -1, where a < 0 or n < 0
template <int a, int n,
typename std::enable_if<is_negative<a> || is_negative<n>>::type>
struct hc {
enum { v = -1 };
};
*/
int main() {
// a^0=0
std::cout << hc<0, 0>::v << " -> 0^0=0\n";
std::cout << hc<3, 0>::v << " -> 3^0=0\n";
// a^n=std::pow
std::cout << hc<1, 1>::v << " -> 1^1=" << std::pow(1, 1) << '\n';
std::cout << hc<2, 2>::v << " -> 2^2=" << std::pow(2, 2) << '\n';
std::cout << hc<0, 2>::v << " -> 0^2=" << std::pow(0, 2) << '\n';
std::cout << hc<3, 2>::v << " -> 3^2=" << std::pow(3, 2) << '\n';
std::cout << hc<3, 7>::v << " -> 3^7=" << std::pow(3, 7) << '\n';
// a^n=-1 for negative a or n
std::cout << hc<-3, 7>::v << " -> -3^7=-1\n";
std::cout << hc<3, -7>::v << " -> 3^-7=-1\n";
std::cout << hc<0, -7>::v << " -> 0^7=-1\n";
std::cout << hc<-3, 0>::v << " -> -3^0=-1\n";
}
There are several ways
Simpler IMO, would be constexpr function
constexpr int hc_impl(int a, int n)
{
if (a < 0 || n < 0) return -1;
if (n == 0) return 0;
int res = 1;
for (int i = 0; i != n; ++n) {
res *= a;
}
return res;
};
template <int a, int n>
struct hc
{
constexpr int v = hc_impl(a, n);
};
The old way with struct, you might add an extra parameter for dispatch, something like:
template <int a, int n, bool b = (a < 0 || n < 0)>
struct hc;
template <int a, int n>
struct hc<a, n, true> {
enum { v = -1 };
};
template <int a>
struct hc<a, 1, true> {
enum { v = -1 };
};
template <int a>
struct hc<a, 0, true> {
enum { v = -1 };
};
template <int a, int n>
struct hc<a, n, false> {
enum { v = a * hc<a, n - 1>::v };
};
// to break recursion from getting to a^0=0
template <int a>
struct hc<a, 1, false> {
enum { v = a };
};
// a^0 = 0
template <int a>
struct hc<a, 0, false> {
enum { v = 0 };
};
This is how I would do it using template constexpr:
template<int a, int n>
constexpr int pow()
{
if ((a < 0) || (n < 0)) return -1;
if (n == 0) return 0;
int result = 1;
for (int i = 0; i < n; i++) result *= a;
return result;
}
int main()
{
static_assert(pow<0,0>() == 0);
static_assert(pow<2, 0>() == 0);
static_assert(pow<-1, 0>() == -1);
static_assert(pow<1, -1>() == -1);
static_assert(pow<2, 3>() == 8);
}
Your partial specialization syntax for the last case is incorrect: you should have something inside <> after template<.....> struct hn.
So, something like this will almost work:
// a ^ n = -1, where a < 0 or n < 0
template <int a, int n,
typename std::enable_if<is_negative<a> || is_negative<n>>::type>
struct hc<a, n> {
enum { v = -1 };
};
enable_if::type is a type which you have to put into a position where it can be SFINAE'd, not just somewhere inside template<>. You typically put it either inside a function signature or inside a partial template specialization.
Like this:
// You have to change your general case definition.
// std::pow
template<int a, int n, typename /*DummyUnusedType*/ = void>
struct hc {
enum { v = a * hc<a, n - 1>::v };
};
// ... your existing definitions here ...
// a ^ n = -1, where a < 0 or n < 0
template <int a, int n>
struct hc<a, n, typename std::enable_if<is_negative<a> || is_negative<n>>::type> {
enum { v = -1 };
};
You actually don't even need is_negative and typename:
struct hc<a, n, std::enable_if_t<(a < 0 || n < 0)>> { // Parens are optional
The only remaining problem is that your <a, 0> case intersects with this one for negative as. You can restrict it for non-negative as using the same trick.
In general, though, constexpr function are superior, as suggested by other answers.

C++ metaprogramming - compile time search tree

UPDATE: sorry for confusing terms - I do not need a binary-tree, but segment-tree or interval-tree.
Imagine I have to statically initialize a search tree each time mine program is executed.
Tree t;
t.add(10, 'Apple');
t.add(20, 'Pear');
t.add(50, 'Orange');
...
t.add(300, 'Cucumber');
..
// then I use it.
int key = 15;
String s = t.lookup(key) // Returns 'Apple' ( as the key is between 10 and 20)
The keys and values in a tree are "static", hard-coded, but have to be maintained from time to time. Is there are metaprogramming trick how to organise key values into binary-search tree (or a skip list) during compile time?
For example the whole search tree is implemented directly in code .text and nothing is held in .data? I can also "predict" number of keys and provide order them.
I suspect you are making a mountain out of a molehill here,
and that it's because:-
You believe that to statically initialize something in C++ you
have to do it at compiletime.
Either you are not acquainted with the
concepts of upper and lower bounds or else you don't know that the
{upper|lower} bound of v in a [partially] ordered sequence S can be
determined by binary search of S, and that you can count on the Standard Library
to do it at least that efficiently.
I think you want to have a statically initialized data structure mapping
integer keys to string literals such that, at runtime, you
can query it with an integer n and very efficiently
retrieve the string literal s (if any), whose key is the largest
that is not larger than n - with the additional proviso, presumably,
that n is not larger than all keys.
If that is right, then the statically initialized data structure you need
is simply a statically initialized map M of integers to string literals.
Template meta-programming is not in the frame.
Because of the (presumed) proviso that that a query shall fail for n larger
than all keys, you will need to include a sentinel value in M with a key 1
larger than the largest you want to find.
Then, for runtime integer n, you query M for the upper bound of n.
The upper bound of n in M is the smallest key larger than n, if any.
If the returned iterator it is M.end() then you have no string for n.
Otherwise, if it == M.begin(), then every key is greater than n,
so again you have no string for n. Otherwise, there must exist a <key,value>
located by --it, and that keymust be the largest key that is not
larger than n. So your string for n is that value.
#include <map>
static const std::map<int,char const *> tab =
{
{ 2,"apple" },
{ 5,"pear" },
{ 9,"orange" },
{ 14,"banana" },
{ 20,"plum" },
{ 20 + 1,nullptr }
};
const char * lookup(int n)
{
auto it = tab.upper_bound(n);
return it == tab.begin() || it == tab.end() ? nullptr : (--it)->second;
}
Prepend that to this example:
#include <iostream>
using namespace std;
int main(void)
{
for (int i = 0; i <= 21; ++i) {
cout << i;
char const *out = lookup(i);
cout << " -> " << (!out ? "Not found" : out) << endl;
}
return 0;
}
and the output will be:
0 -> Not found
1 -> Not found
2 -> apple
3 -> apple
4 -> apple
5 -> pear
6 -> pear
7 -> pear
8 -> pear
9 -> orange
10 -> orange
11 -> orange
12 -> orange
13 -> orange
14 -> banana
15 -> banana
16 -> banana
17 -> banana
18 -> banana
19 -> banana
20 -> plum
21 -> Not found
Now tab in this program is a static data structure, but it is not
initialized at compiletime. It is initialized in the global static
initialization of your program, before main is called. Unless you
have a requirement to shave nanoseconds off your program startup, I
can't think why you would need the map to be initialized at compiletime.
If nevertheless you do require it to be initialized at compiletime,
it is just a little fiddlier than this. You will need the map to be
a constexpr
object, meaning the compiler can construct it at compiletime; and for
that it must be of a literal type;
and that means you cannot use std::map, because it is not a literal type.
Therefore you will have to use instead:
constexpr std::pair<int,char const *> tab[]
{
{ 2,"apple" },
{ 5,"pear" },
{ 9,"orange" },
{ 14,"banana" },
{ 20,"plum" },
{ 20 + 1,nullptr }
};
or similar, and implement lookup(n) in essentially the manner shown,
but invoking std::upper_bound upon tab. There you'll find the
slightly fiddlier bits, which I'll leave you for the exercise, if you
want it.
I finally created what I wanted to achieve. It's overcomplicated and it looks like compiler optimizers are much smarter then I thought.
// Log "function"
template <int N>
struct LOG
{
static const int value = LOG<N/2>::value + 1;
};
template<>
struct LOG<0>
{
static const int value = 0;
};
// pow "function"
template <int N>
struct POW
{
static const int value = POW<N-1>::value * 2;
};
template<>
struct POW<1>
{
static const int value = 2;
};
template<>
struct POW<0>
{
static const int value = 1;
};
// Pair <key, value> to be a payload in a type list
template<int k, char v>
struct Pair
{
static const int key = k;
static const int value = v;
};
// type list manipulator - access n-th element
template <size_t, class...> struct element;
template <class TT, class...TTs>
struct element<0, TT, TTs...>
{
typedef TT type;
};
template <size_t K, class TT, class...TTs>
struct element<K, TT, TTs...>
{
typedef typename element<K-1, TTs...>::type type;
};
template<class... Ts>
struct V;
// Binary split search algorithm (pure templatized)
template<class T, class... Ts>
struct V<T, Ts...> : private V<Ts...>
{
template<size_t N = sizeof...(Ts), size_t level = LOG<sizeof...(Ts)+1>::value>
struct impl
{
template<size_t IDX>
inline static char search_impl(size_t n)
{
using namespace std;
static const int depth = LOG<N>::value;
static const int layer = depth - level;
static const int key = element<IDX, T, Ts...>::type::key;
static const size_t left_idx = IDX - ( N / POW<layer + 2>::value + 1);
static const size_t right_idx =
IDX + ( N / POW<layer + 2>::value + 1) > sizeof...(Ts) ?
sizeof...(Ts) :
IDX + ( N / POW<layer + 2>::value + 1);
//std::cout << setfill('*') << setw(layer) << ' '
// << "Level:" << level << " of:" << depth << std::endl
// << std::setw(layer) << ' '
// << "IDX/val/layer/POW/level: "
// << " " << IDX
// << "/" << key
// << "/" << layer
// << "/" << POW<layer>::value
// << "/" << level
// << "/" << left_idx
// << "/" << right_idx
// << std::endl;
if ( n < key )
return V<T, Ts...>::impl<N, level-1>::template search_impl<left_idx>(n);
else
return V<T, Ts...>::impl<N, level-1>::template search_impl<right_idx>(n);
}
};
template<size_t N>
struct impl<N,1>
{
template<size_t IDX>
inline static char search_impl(size_t n)
{
static const int key = element<IDX, T, Ts...>::type::key;
static const char value1 = element<IDX-1, T, Ts...>::type::value;
static const char value2 = element<IDX, T, Ts...>::type::value;
if ( n < key )
{
//std::cout << " *" << value1 << ' ' << IDX << std::endl;
return value1;
} else {
//std::cout << " *" << value2 << ' ' << IDX << std::endl;
return value2;
}
}
};
static void print()
{
std::cout << typeid(T).name() << ' ' << T::key << ' ' << (char)T::value << std::endl;
V<Ts...>::print();
}
static char search(size_t n)
{
static const size_t level = LOG<sizeof...(Ts)+1>::value;
static const size_t N = sizeof...(Ts);
static const int height = LOG<N>::value;
static const size_t root_idx = N / 2 + 1;
static const int key = element<root_idx, T, Ts...>::type::key;
//std::cout << "Level:" << level << " of:" << height << std::endl
// << "IDX/val: "
// << " " << root_idx
// << "/" << input[root_idx]
// << std::endl;
static const size_t left_idx = root_idx - ( N / POW<2>::value + 1);
static const size_t right_idx = root_idx + ( N / POW<2>::value + 1);
if( n < key)
return V<T, Ts...>::impl<N, level-1>::template search_impl<left_idx>(n);
else
return V<T, Ts...>::impl<N, level-1>::template search_impl<right_idx>(n);
}
};
template<>
struct V<>
{
static void print()
{}
};
int main(int argc, char *argv[])
{
int i = std::stoi(argv[1]);
typedef V<
Pair< 0x1,'a'>,
Pair< 0x11,'b'>,
Pair< 0x21,'c'>,
Pair< 0x31,'d'>,
Pair< 0x41,'e'>,
Pair< 0x51,'f'>,
Pair< 0x61,'g'>,
Pair< 0x71,'h'>,
Pair< 0x81,'i'>,
Pair< 0x91,'j'>,
Pair<0x101,'k'>,
Pair<0x111,'l'>,
Pair<0x121,'m'>,
Pair<0x131,'n'>,
Pair<0x141,'o'>
> TV;
std::cout << (char)TV::search(i) << std::endl;
return 0;
};
So this is it. Mine goal was to "force" the compiler to put all the constants into the code. As nothing is kept in the data segment. The resulting code inlines all the search_impl<*> methods together and the result contains only "cmp" and "jae" instructions. But it looks like a reasonable compiler will do this anyway, if the array to be searched is defined as const static.
I would use a switch to do the lookup.
The compiler is free to use a jump table, binary search, or any other technique to optimize the lookup. For most switch tables, the compiler will generally emit the fastest possible thing.
switch (key)
{
case 10: return "Apple";
case 20: return "Pear";
...
}

How to pass optional arguments to a method in C++?

How to pass optional arguments to a method in C++ ?
Any code snippet...
Here is an example of passing mode as optional parameter
void myfunc(int blah, int mode = 0)
{
if (mode == 0)
do_something();
else
do_something_else();
}
you can call myfunc in both ways and both are valid
myfunc(10); // Mode will be set to default 0
myfunc(10, 1); // Mode will be set to 1
An important rule with respect to default parameter usage:
Default parameters should be specified at right most end, once you specify a default value parameter you cannot specify non default parameter again.
ex:
int DoSomething(int x, int y = 10, int z) -----------> Not Allowed
int DoSomething(int x, int z, int y = 10) -----------> Allowed
It might be interesting to some of you that in case of multiple default parameters:
void printValues(int x=10, int y=20, int z=30)
{
std::cout << "Values: " << x << " " << y << " " << z << '\n';
}
Given the following function calls:
printValues(1, 2, 3);
printValues(1, 2);
printValues(1);
printValues();
The following output is produced:
Values: 1 2 3
Values: 1 2 30
Values: 1 20 30
Values: 10 20 30
Reference: http://www.learncpp.com/cpp-tutorial/77-default-parameters/
To follow the example given here, but to clarify syntax with the use of header files, the function forward declaration contains the optional parameter default value.
myfile.h
void myfunc(int blah, int mode = 0);
myfile.cpp
void myfunc(int blah, int mode) /* mode = 0 */
{
if (mode == 0)
do_something();
else
do_something_else();
}
With the introduction of std::optional in C++17 you can pass optional arguments:
#include <iostream>
#include <string>
#include <optional>
void myfunc(const std::string& id, const std::optional<std::string>& param = std::nullopt)
{
std::cout << "id=" << id << ", param=";
if (param)
std::cout << *param << std::endl;
else
std::cout << "<parameter not set>" << std::endl;
}
int main()
{
myfunc("first");
myfunc("second" , "something");
}
Output:
id=first param=<parameter not set>
id=second param=something
See https://en.cppreference.com/w/cpp/utility/optional
Use default parameters
template <typename T>
void func(T a, T b = T()) {
std::cout << a << b;
}
int main()
{
func(1,4); // a = 1, b = 4
func(1); // a = 1, b = 0
std::string x = "Hello";
std::string y = "World";
func(x,y); // a = "Hello", b ="World"
func(x); // a = "Hello", b = ""
}
Note : The following are ill-formed
template <typename T>
void func(T a = T(), T b )
template <typename T>
void func(T a, T b = a )
With commas separating them, just like parameters without default values.
int func( int x = 0, int y = 0 );
func(); // doesn't pass optional parameters, defaults are used, x = 0 and y = 0
func(1, 2); // provides optional parameters, x = 1 and y = 2
Typically by setting a default value for a parameter:
int func(int a, int b = -1) {
std::cout << "a = " << a;
if (b != -1)
std::cout << ", b = " << b;
std::cout << "\n";
}
int main() {
func(1, 2); // prints "a=1, b=2\n"
func(3); // prints "a=3\n"
return 0;
}
Jus adding to accepted ans of #Pramendra , If you have declaration and definition of function, only in declaration the default param need to be specified

Getting template metaprogramming compile-time constants at runtime

Background
Consider the following:
template <unsigned N>
struct Fibonacci
{
enum
{
value = Fibonacci<N-1>::value + Fibonacci<N-2>::value
};
};
template <>
struct Fibonacci<1>
{
enum
{
value = 1
};
};
template <>
struct Fibonacci<0>
{
enum
{
value = 0
};
};
This is a common example and we can get the value of a Fibonacci number as a compile-time constant:
int main(void)
{
std::cout << "Fibonacci(15) = ";
std::cout << Fibonacci<15>::value;
std::cout << std::endl;
}
But you obviously cannot get the value at runtime:
int main(void)
{
std::srand(static_cast<unsigned>(std::time(0)));
// ensure the table exists up to a certain size
// (even though the rest of the code won't work)
static const unsigned fibbMax = 20;
Fibonacci<fibbMax>::value;
// get index into sequence
unsigned fibb = std::rand() % fibbMax;
std::cout << "Fibonacci(" << fibb << ") = ";
std::cout << Fibonacci<fibb>::value;
std::cout << std::endl;
}
Because fibb is not a compile-time constant.
Question
So my question is:
What is the best way to peek into this table at run-time? The most obvious solution (and "solution" should be taken lightly), is to have a large switch statement:
unsigned fibonacci(unsigned index)
{
switch (index)
{
case 0:
return Fibonacci<0>::value;
case 1:
return Fibonacci<1>::value;
case 2:
return Fibonacci<2>::value;
.
.
.
case 20:
return Fibonacci<20>::value;
default:
return fibonacci(index - 1) + fibonacci(index - 2);
}
}
int main(void)
{
std::srand(static_cast<unsigned>(std::time(0)));
static const unsigned fibbMax = 20;
// get index into sequence
unsigned fibb = std::rand() % fibbMax;
std::cout << "Fibonacci(" << fibb << ") = ";
std::cout << fibonacci(fibb);
std::cout << std::endl;
}
But now the size of the table is very hard coded and it wouldn't be easy to expand it to say, 40.
The only one I came up with that has a similiar method of query is this:
template <int TableSize = 40>
class FibonacciTable
{
public:
enum
{
max = TableSize
};
static unsigned get(unsigned index)
{
if (index == TableSize)
{
return Fibonacci<TableSize>::value;
}
else
{
// too far, pass downwards
return FibonacciTable<TableSize - 1>::get(index);
}
}
};
template <>
class FibonacciTable<0>
{
public:
enum
{
max = 0
};
static unsigned get(unsigned)
{
// doesn't matter, no where else to go.
// must be 0, or the original value was
// not in table
return 0;
}
};
int main(void)
{
std::srand(static_cast<unsigned>(std::time(0)));
// get index into sequence
unsigned fibb = std::rand() % FibonacciTable<>::max;
std::cout << "Fibonacci(" << fibb << ") = ";
std::cout << FibonacciTable<>::get(fibb);
std::cout << std::endl;
}
Which seems to work great. The only two problems I see are:
Potentially large call stack, since calculating Fibonacci<2> requires we go through TableMax all the way to 2, and:
If the value is outside of the table, it returns zero as opposed to calculating it.
So is there something I am missing? It seems there should be a better way to pick out these values at runtime.
A template metaprogramming version of a switch statement perhaps, that generates a switch statement up to a certain number?
Thanks in advance.
template <unsigned long N>
struct Fibonacci
{
enum
{
value = Fibonacci<N-1>::value + Fibonacci<N-2>::value
};
static void add_values(vector<unsigned long>& v)
{
Fibonacci<N-1>::add_values(v);
v.push_back(value);
}
};
template <>
struct Fibonacci<0>
{
enum
{
value = 0
};
static void add_values(vector<unsigned long>& v)
{
v.push_back(value);
}
};
template <>
struct Fibonacci<1>
{
enum
{
value = 1
};
static void add_values(vector<unsigned long>& v)
{
Fibonacci<0>::add_values(v);
v.push_back(value);
}
};
int main()
{
vector<unsigned long> fibonacci_seq;
Fibonacci<45>::add_values(fibonacci_seq);
for (int i = 0; i <= 45; ++i)
cout << "F" << i << " is " << fibonacci_seq[i] << '\n';
}
After much thought into the problem, I came up with this solution. Of course, you still have to add the values to a container at run-time, but (importantly) they are not computed at run-time.
As a side note, it's important not to define Fibonacci<1> above Fibonacci<0>, or your compiler will get very confused when it resolves the call to Fibonacci<0>::add_values, since Fibonacci<0>'s template specialization has not been specified.
Of course, TMP has its limitations: You need a precomputed maximum, and getting the values at run-time requires recursion (since templates are defined recursively).
I know this question is old, but it intrigued me and I had to have a go at doing without a dynamic container filled at runtime:
#ifndef _FIBONACCI_HPP
#define _FIBONACCI_HPP
template <unsigned long N>
struct Fibonacci
{
static const unsigned long long value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;
static unsigned long long get_value(unsigned long n)
{
switch (n) {
case N:
return value;
default:
return n < N ? Fibonacci<N-1>::get_value(n)
: get_value(n-2) + get_value(n-1);
}
}
};
template <>
struct Fibonacci<0>
{
static const unsigned long long value = 0;
static unsigned long long get_value(unsigned long n)
{
return value;
}
};
template <>
struct Fibonacci<1>
{
static const unsigned long long value = 1;
static unsigned long get_value(unsigned long n)
{
if(n == N){
return value;
}else{
return 0; // For `Fibonacci<N>::get(0);`
}
}
};
#endif
This seems to work, and when compiled with optimizations (not sure if you were going to allow that), the call stack does not get to deep - there is normal runtime recursion on the stack of course for values (arguments) n > N, where N is the TableSize used in the template instantiation. However, once you go below the TableSize the generated code substitutes a constant computed at compile time, or at worst a value "computed" by dropping through a jump table (compiled in gcc with -c -g -Wa,-adhlns=main.s and checked the listing), the same as I reckon your explicit switch statement would result in.
When used like this:
int main()
{
std::cout << "F" << 39 << " is " << Fibonacci<40>::get_value(39) << '\n';
std::cout << "F" << 45 << " is " << Fibonacci<40>::get_value(45) << '\n';
}
There is no call to a computation at all in the first case (value computed at compile time), and in the second case the call stack depth is at worst:
fibtest.exe!Fibonacci<40>::get_value(unsigned long n=41) Line 18 + 0xe bytes C++
fibtest.exe!Fibonacci<40>::get_value(unsigned long n=42) Line 18 + 0x2c bytes C++
fibtest.exe!Fibonacci<40>::get_value(unsigned long n=43) Line 18 + 0x2c bytes C++
fibtest.exe!Fibonacci<40>::get_value(unsigned long n=45) Line 18 + 0xe bytes C++
fibtest.exe!main() Line 9 + 0x7 bytes C++
fibtest.exe!__tmainCRTStartup() Line 597 + 0x17 bytes C
I.e. it recurses until it finds a value in the "Table". (verified by stepping through Disassembly in the debugger line by line, also by replacing the test ints by a random number <= 45)
The recursive part could also be replaced by the linear iterative solution:
static unsigned long long get_value(unsigned long n)
{
switch (n) {
case N:
return value;
default:
if (n < N) {
return Fibonacci<N-1>::get_value(n);
} else {
// n > N
unsigned long long i = Fibonacci<N-1>::value, j = value, t;
for (unsigned long k = N; k < n; k++) {
t = i + j;
i = j;
j = t;
}
return j;
}
}
}
If you have C++ compiler which supports variadic templates (C++0x standard ) you can save fibonacii sequence in a tuple at the compile time. At runtime you can access any element from that tuple by indexing.
#include <tuple>
#include <iostream>
template<int N>
struct Fib
{
enum { value = Fib<N-1>::value + Fib<N-2>::value };
};
template<>
struct Fib<1>
{
enum { value = 1 };
};
template<>
struct Fib<0>
{
enum { value = 0 };
};
// ----------------------
template<int N, typename Tuple, typename ... Types>
struct make_fibtuple_impl;
template<int N, typename ... Types>
struct make_fibtuple_impl<N, std::tuple<Types...> >
{
typedef typename make_fibtuple_impl<N-1, std::tuple<Fib<N>, Types... > >::type type;
};
template<typename ... Types>
struct make_fibtuple_impl<0, std::tuple<Types...> >
{
typedef std::tuple<Fib<0>, Types... > type;
};
template<int N>
struct make_fibtuple : make_fibtuple_impl<N, std::tuple<> >
{};
int main()
{
auto tup = typename make_fibtuple<25>::type();
std::cout << std::get<20>(tup).value;
std::cout << std::endl;
return 0;
}
With C++11: you may create a std::array and a simple getter: https://ideone.com/F0b4D3
namespace detail
{
template <std::size_t N>
struct Fibo :
std::integral_constant<size_t, Fibo<N - 1>::value + Fibo<N - 2>::value>
{
static_assert(Fibo<N - 1>::value + Fibo<N - 2>::value >= Fibo<N - 1>::value,
"overflow");
};
template <> struct Fibo<0u> : std::integral_constant<size_t, 0u> {};
template <> struct Fibo<1u> : std::integral_constant<size_t, 1u> {};
template <std::size_t ... Is>
constexpr std::size_t fibo(std::size_t n, index_sequence<Is...>)
{
return const_cast<const std::array<std::size_t, sizeof...(Is)>&&>(
std::array<std::size_t, sizeof...(Is)>{{Fibo<Is>::value...}})[n];
}
template <std::size_t N>
constexpr std::size_t fibo(std::size_t n)
{
return n < N ?
fibo(n, make_index_sequence<N>()) :
throw std::runtime_error("out of bound");
}
} // namespace detail
constexpr std::size_t fibo(std::size_t n)
{
// 48u is the highest
return detail::fibo<48u>(n);
}
In C++14, you can simplify some function:
template <std::size_t ... Is>
constexpr std::size_t fibo(std::size_t n, index_sequence<Is...>)
{
constexpr std::array<std::size_t, sizeof...(Is)> fibos{{Fibo<Is>::value...}};
return fibos[n];
}
My idea is to recursively save the fibonacci sequence in the variadic templates then convert it into an array. All of this are done at compile-time.
For example with n = 5 we have:
F<5>::array
= F<4, 0>::array
= F<3, 0, 1>::array
= F<2, 0, 1, 1>::array
= F<1, 0, 1, 1, 2>::array
= F<0, 0, 1, 1, 2, 3>::array
= { 0, 1, 1, 2, 3 }
Then we can index the array at runtime.
My C++14 implementation:
#include <cstdint>
#include <array>
#include <iostream>
template<uint64_t n>
struct Helper { static constexpr uint64_t value = Helper<n - 1>::value + Helper<n - 2>::value; };
template<>
struct Helper<0> { static constexpr uint64_t value = 0; };
template<>
struct Helper<1> { static constexpr uint64_t value = 1; };
template<u_int64_t x>
class Fib {
private:
template<u_int64_t n, u_int64_t...rest>
struct Get {
static constexpr std::array<u_int64_t, n + sizeof...(rest)> value = Get<n - 1, rest..., Helper<sizeof...(rest)>::value>::value;
};
template<u_int64_t...rest>
struct Get<0, rest...> {
static constexpr std::array<u_int64_t, sizeof...(rest)> value{rest...};
};
public:
static constexpr std::array<u_int64_t, x> sequence = Get<x>::value;
};
template<u_int64_t x>
constexpr std::array<u_int64_t, x> Fib<x>::sequence;
int main() {
for (int i = 0; i < 45; i++) std::cout << "F" << i << " = " << Fib<45>::sequence[i] << std::endl;
}
One of the basic tennants of C (and for the most part C++) is that you don't pay for what you don't need.
The automatic generation of look-up tables is just not something that the compiler needs to do for you. Even if you need that functionality, not everyone else necessarly does.
If you want a lookup table, write a program to make one. Then use that data in your program.
Don't use a template metaprogram if you want values to be calculated at runtime, just use a regular program to calculate values.
You can generate the switch or a static array using preprocessor metaprogramming techniques.
It is a good decision if the complexity does not exceed the limitations of that approach, and you prefer not extending your toolchain with extra steps that generate code or data.