Consider a compile-time function of the form:
template <unsigned int Value>
constexpr unsigned int function()
{
// Just for the example, but it could be very complicated here
return Value*Value;
}
How to write the runtime equivalent that will call the right compile-time version using template metaprogramming, knowing that the value will always be in the [From, To[ interval:
template <unsigned int From, unsigned int To, /* Something here */>
constexpr unsigned int function(const unsigned int value)
{
// Something here
}
The branching to the right version should be as fast as possible.
For example function<0, 32>(6) (runtime version) should call function<6>() (compile-time version).
EDIT: Explanation:
Why do I want to do this? This function (real use case) need to be as fast as possible (supercomputing issues). By providing the parameter at compile-time, I can generate very efficient code. If I simply move the value from the template parameter to a function parameter, the code is between 10 and 100 times slower. But in fact, this parameter does not have a very wide range of possible values (like between 0 and 32): so it would be far more efficient to branch at runtime on the right compile-time version.
The easiest way is to set up a recursive cascading if/recurse chain.
#define RETURNS(X) -> decltype(X) { return (X); }
template<unsigned From, unsigned To, typename Target>
struct CallIf {
constexpr auto operator()( unsigned N )
RETURNS( (N==From)?Target::template func<From>():CallIf<From+1, To, Target>()( N ) );
};
template<unsigned From, typename Target>
struct CallIf<From, From+1, Target> {
constexpr auto operator()( unsigned N )
RETURNS( Target::template func<From>() );
};
struct Func {
template<unsigned V>
constexpr unsigned func() const {
return function<V>();
}
};
or something like that, and rely on the compiler collapsing that chain of ifs down to one. (if you know the return type, you can do away with that annoying RETURNS macro, or if you have C++1y features you can do the same).
Now, you might want to compare this to a version that does a binary search on value in that range, using a similar recursive call case. Similarly, you could do it by checking and setting bits in a compile time value.
template<unsigned From, unsigned To, typename Target>
struct CallIf {
enum { Mid = From + (To-From)/2 }; // avoid overflow risk
constexpr auto operator()( unsigned N )
RETURNS( (N>=Mid)?CallIf<Mid, To, Target>()(N):CallIf<From,Mid,Target>()(N) );
};
with the same specialization for the 1-width case.
Another approach would be to set up a static array of invocations of function<V> and then do an array dereference at run time:
template<unsigned...> struct indexes {};
template<unsigned Min, unsigned Max, unsigned... Is> struct make_indexes:make_indexes<Min, Max-1, Max-1, Is...> {};
template<unsigned Min, unsigned... Is> struct make_indexes<Min, Min, Is...>:indexes<Is...> {};
template<unsigned From, unsigned To, typename Target>
struct CallIf {
template<unsigned... Is>
unsigned Invoke( indexes<Is...>, unsigned N ) const {
typedef unsigned(*target)();
static target ts[] = { &(function<Is>)... };
return ts[N-From]();
};
unsigned operator()( unsigned N ) const {
return Invoke( make_indexes<From, To>(), N );
}
};
although I'm not sure how to make the above constexpr easily in C++11 at least, and I skipped out on doing return-type deduction.
None of the above are tested or compiled, so most likely will require some repair. But the core concept will work. The specialization might need some work: doing <From, From+1 to terminate is something I haven't done in practice: if that causes issues, you can do <From, Width based helper, and specialize on Width=1.
I personally call this technique (embodied in the CallIf type above) the "magic switch", where we take a run time valid and "magically" make it a compile time value. I only mention this because you can probably find me talking about it on stack overflow by googling Yakk and "magic switch" (and site:stackoverflow.com) for other variations, some of which have been compiled and have live examples attached.
Finally, while the last version (the manual jump table) may be fastest, if you are calling it so often that the speed of this invocation is key, you might want to think about wrapping not just the call site, but the algorithm surrounding it in a magic switch: do the dispatching earlier. If, however, you only get the index at the last moment, and you are ok with a non-constexpr call, it should work. Note that static arrays will be created for each Function and To and From used.
You may create an (constexpr) array of results, something like :
#if 1 // Not in C++11
template <std::size_t ...> struct index_sequence {};
template <std::size_t I, std::size_t ...Is>
struct make_index_sequence : make_index_sequence < I - 1, I - 1, Is... > {};
template <std::size_t ... Is>
struct make_index_sequence<0, Is...> : index_sequence<Is...> {};
#endif
template <unsigned int Value>
constexpr unsigned int function()
{
// Just for the example, but it could be very complicated here
return Value * Value;
}
namespace detail
{
template <std::size_t From, std::size_t...Is>
struct result_array
{
static constexpr std::array<unsigned int, sizeof...(Is)> values = {{::function<From + Is>()...}};
};
template <std::size_t From, std::size_t...Is>
constexpr std::array<unsigned int, sizeof...(Is)> result_array<From, Is...>::values;
template <std::size_t From, std::size_t...Is>
constexpr unsigned int function(unsigned int value, index_sequence<Is...>)
{
return result_array<From, Is...>::values[value - From];
}
} // namespace detail
template <unsigned int From, unsigned int To>
constexpr unsigned int function(const unsigned int value)
{
static_assert(From < To, "Invalid template parameters");
return detail::function<From>(value, make_index_sequence<std::size_t(To + 1 - From)>());
}
Related
I am trying to achieve the following: Given a POD struct I want to generate compile time metadata on the struct automatically (i.e I don't want to have to register every field by hand).
The metadata I need is just the number of fields and the byte size of each field.
So for example for the struct:
struct MyData
{
float field1;
int field2;
}
All we need is FIELD_NUM(MyData) to return 2 and FIELD_SIZE(MyData, 0) to return 4.
My current approach is terrible. I don't even use the built in preprocessor, I have a python parser that searches for a comment on top of the structure and it builds a dictionary of all registered structures, it then replaces the patterns in the code with their numeric values. But this is very limited, for example I don't even handle templates because at that point I might as well make my own C++ compiler.
Using templated meta programming
Ok so in the comments someone suggested a very interesting video that I am watching. It suggests that to get the number of fields in a POD you can do this:
template <std::size_t I>
struct ubiq_constructor
{
template <class Type>
constexpr operator Type&() const noexcept;
};
template <class T, std::size_t I0, std::size_t... I>
constexpr auto detect_fields_count(std::size_t& out, std::index_sequence<I0, I...>)
-> decltype( T{ ubiq_constructor<I0>{}, ubiq_constructor<I>{}... } )
{ out = sizeof...(I) + 1; }
template <class T, std::size_t... I>
constexpr void detect_fields_count(std::size_t& out, std::index_sequence<I...>) {
detect_fields_count<T>(out, std::make_index_sequence<sizeof...(I) - 1>{});
}
The gist of it is, try to initialize the struct with a number of parameters equal to the struct size, if that fails, reduce the parameters by one, keep going until the number of parameters matches the fields in the struct.
However when I try to call it like this:
struct POD {
int f1;
float f2;
char h;
};
std::size_t size;
detect_fields_count<POD>(size, std::make_index_sequence<sizeof(POD)>());
cout << "size:" << size << endl;
I get a segmentation fault on pre-initialization. How do you call those functions?
I have a class with a template that accepts an integer:
template <unsigned int N>
class Example {};
I'm looking for a way to define a (member)function that accepts some amount of Example objects as arguments. The amount is to be determined by N, so the function would be used like this:
Function(Example<2>(), Example<2>());
Function(Example<3>(), Example<3>(), Example<3>());
What I tried so far:
Using an initializer list, one is able to pass a set of objects to the function:
template <unsigned int N>
void Function(std::initializer_list<Example<N>> list);
//...
Function({Example<2>(), Example<2>()});
However, the problem besides the fact that really only one argument is passed(the list), is that with this method any number of arguments can be used:
Function({Example<2>()});
I also tried using a variadic function:
template <unsigned int N>
void Function(Example<N> e...)
{
va_list args;
va_start(args, e);
//...
}
Function(Example<2>(), Example<2>());
This makes it possible to use real parameters, but the problem of using any number of arguments remains, and it's not possible to know how many arguments were actually passed.
Assuming you want the number of arguments to be deduced from the Example<N> type, and that all Example<I> should share the same such N, a C++17 solution might be
template <unsigned int... I>
auto Function( Example<I>... ) ->
std::enable_if_t<( ( I == sizeof...(I) ) && ... )>
{
// or static_assert() if you always want an error
}
Make Function a variadic template and use std::enable_if_t to constrain your it:
Some IsExample trait can be used to make sure that all arguments are instances of Example
sizeof...(pack) can be used to get the size of the parameter pack
template <unsigned int N, typename... Ts>
auto Function(Ts... xs)
-> std::enable_if_t<(IsExample<Ts>::value && ...)
&& (sizeof...(Ts) == N)>
{
}
live example on wandbox
You should utilize variadic function template with static_assert. Unlike approaches involving enable_if this one will produce a readable error message if incorrect arguments are passed.
template<unsigned int ... I>
void Function(Example<I>... items)
{
static_assert
(
true && (... && (static_cast<unsigned int>(sizeof...(I)) == I))
, "This function accepts N arguments of type Example<N>"
);
}
Online compiler
There are many answers that cover SFINAE friendly based constraints, but I don't like placing my SFINAE in the return value:
template <unsigned int... Is,
std::enable_if_t<( ( Is == sizeof...(Is) ) && ... ), bool> = true
>
void Function( Example<Is>... examples )
{
// code
}
or
template<bool b>
using test_requirement = std::enable_if_t<b, bool>;
template <unsigned int... Is,
test_requirement<( ( Is == sizeof...(Is) ) && ... )> = true
>
void Function( Example<Is>... examples )
{
// code
}
+1 for the Massimiliano Janes's elegant solution.
Unfortunately use folding so works only for C++17.
To test, with C++11/C++14, that all I are equals to sizeof...(I) (and maybe that sizeof...(I) is equal to N, where N is the class template argument), it's enough test that a variadic type, that receive unsigned values, is the same type with a different order of values.
I mean: declaring a trivial struct as
template <std::size_t ... Is>
struct IList;
the test can be
std::is_same<IList<N, sizeof...(Is), Is...>,
IList<sizeof...(Is), Is..., N>>::value
Starting from C++14 it's possible to use std::index_sequence instead of IList.
So Example can be written as
template <unsigned int N>
struct Example
{
template <unsigned int ... Is>
auto Function (Example<Is> ...)
-> typename std::enable_if<
std::is_same<IList<N, sizeof...(Is), Is...>,
IList<sizeof...(Is), Is..., N>>::value>::type
{ /* do something */ }
};
The following is a example of use (but remember to include <type_traits>)
int main()
{
Example<1U> e1;
Example<2U> e2;
// e1.Function(); // error
e1.Function(Example<1>{}); // compile
//e1.Function(Example<1>{}, Example<1>{}); // error
// e2.Function(); // error
//e2.Function(Example<2>{}); // error
e2.Function(Example<2>{}, Example<2>{}); // compile
//e2.Function(Example<2>{}, Example<2>{}, Example<2>{}); // error
}
While trying to reply to this question, I found my self in the need of creating a bunch of parameters for a variadic function on the fly where:
the number of the parameters is not given
the types are all the same, but unknown (even if they must be default constructible)
At runtime, the standard containers and a for loop can be used to do that.
Anyway, I'd like to generate a set of parameters at compile time, so as to be able to forward them to a variadic function.
Because of that, a std::tuple seemed the obvious solution.
Here arose the question: given a size N and a default constructible type T at compile time, how can I write a function to generate a tuple of the given size?
I'm looking for something like this:
auto tup = gen<MyType, N>();
On SO is a notable example of a recursive generator based structs but I was struggling with a function based solution and I've not been able to find it anywhere.
A correctly written forwarding function (a la std::apply) should work with std::array<T, N> and anything else that implements the std::tuple_size/std::get interface. That said,
template<size_t, class T>
using T_ = T;
template<class T, size_t... Is>
auto gen(std::index_sequence<Is...>) { return std::tuple<T_<Is, T>...>{}; }
template<class T, size_t N>
auto gen() { return gen<T>(std::make_index_sequence<N>{}); }
Here is a possible implementation of such a function:
#include<utility>
#include<tuple>
template<typename T>
constexpr auto
params(std::index_sequence<0>) {
return std::tuple<T>{};
}
template<typename T, std::size_t I, std::size_t... O>
constexpr auto
params(std::index_sequence<I, O...>) {
auto tup = std::tuple<T>{ T{} };
auto seq = std::make_index_sequence<sizeof...(O)>{};
return std::tuple_cat(tup, params<T>(seq));
}
template<typename T, std::size_t N>
constexpr auto
gen(std::integral_constant<std::size_t, N>) {
return params<T>(std::make_index_sequence<N>{});
}
int main() {
auto tup = gen<int>(std::integral_constant<std::size_t, 3>{});
static_assert(std::tuple_size<decltype(tup)>::value == 3, "!");
}
For the sake of simplicity, I've used int as a type.
With a small effort, user defined types can be used and the constraint of having them default constructible can be relaxed.
Here is a code snippet illustrating my question:
const float D = 0.1F;
const float A[4] = {sin(0*D), sin(1*D), sin(2*D), sin(3*D)};
Imagine that global array A is much longer and you don't want to do all of this repetitive typing. Is there a shorter way to initialize array A at compile or initialization time, i.e. without having to write initialization function and call it somewhere in my program?
You could initialize A during dynamic initialization time as follows:
const float *init_a(float x_)
{
static float data[4];
for(unsigned i=0; i<4; ++i)
data[i]=sin(i*x_);
return data;
}
const float D=0.1f;
const float *A=init_a(D);
You may use code generator to generate initialization code. That is, write program that will write your initialization code for you. You may actually calculate values at generation-time.
Remember that C++ allows placing , after last element. It's also isn't necessary to specify array size. These two things should ease writing of generator.
This simple python code should work well:
from math import sin
print('const float A[', N, '] = {')
for i in range(N):
print('\t', sin(i*D), ',', sep='')
print('};')
Ok I just realized this doesn't actually answer the question, because it specifies "without having to write initialization function and call it somewhere in my program?" But I can't think of a convenient alternative.
template<size_t N>
std::array<float, N> GetLookupTable(float d)
{
std::array<float, N> table;
// .. populate table here
return table;
}
// a global somewhere
(static?) const auto Table_10x5 = GetLookupTable<10>(5.0f);
This first part is obsolete in C++14, but not long:
template<unsigned...>struct indexes { using type=indexes; };
template<unsigned Max, unsigned...Is>struct make_indexes:make_indexes<Max-1,Max-1,Is...>{};
template<unsigned...Is>struct make_indexes<0,Is...>:indexes<Is...>{};
template<unsigned Max>using make_indexes_t=typename make_indexes<Max>::type;
this is some template meta programming that lets us create and pass around bundles of indexes.
Then some code to generate the array:
namespace details {
template<std::size_t N, unsigned...Is>
std::array<float, N> poly_sin(float src, indexes<Is...>) {
return { (Is*sin(src))... };
}
}
template<std::size_t N>
std::array<float, N> poly_sin(float src) {
return details::poly_sin<N>( src, make_indexes_t<N>{} );
}
The first method takes indexes<Is...> and we plan that Is... is 0, 1, 2, ..., N-1. It then expands the parameter pack into a std::array of the right size.
make_indexes_t<N>{} expands (at compile time) to indexes<0, 1, 2, ..., N-1>{}, which is then passed to details::poly_sin, which then can deduce the Is... and use them within itself.
And point of use:
const float D = 0.1F;
const auto A = poly_sin<4>(D);
if you had a constexpr sin function, you could even make poly_sin a constexpr function and have it basically guaranteed to be evaluated at compile time.
If this is the case, make D constexpr and same with the two poly_sin functions.
As written, this occurs at dynamic initialization time.
While it appears that the array is copied twice, RVO elision means that any decent compiler will directly construct it in A.
If you want to be able to do this in general, first start with the above indexes code. Then add this:
template<class Sig>using result_of_t=typename std::result_of<Sig>::type;
namespace details {
template<std::size_t N, class F, unsigned... Is>
std::array< result_of_t< F(unsigned) >, N >
make_array( F&& f, indexes<Is...> ) {
return { f( Is )... };
}
}
template<std::size_t N, class F>
std::array< result_of_t< F(unsigned) >, N >
make_array( F&& f ) {
return details::make_array( std::forward<F>(f), make_indexes_t<N>{} );
}
const auto A = make_array<4>( [](unsigned i){ return float(i*sin(D)); } );
which uses a lambda to pass in the code that is repeated to build the array. Sadly, lambdas are not by default constexpr so you cannot do it at compile time.
You could either use boost.preprocessor and in particular the BOOST_PP_ENUM macro, like the example below:
#include <iostream>
#include <cmath>
#include <boost/preprocessor/repetition/enum.hpp>
#define SIZE 4
#define D 0.1
#define ORDER(z, n, text) std::sin(n * D)
double const A[SIZE] = { BOOST_PP_ENUM(SIZE, ORDER, ~) };
int main() {
for(auto i : A) std::cout << i << std::endl;
}
Or, you could use std::array instead of raw arrays, and via use of template meta-programming to generate a std::array at compile time. like the example below:
template<typename T, typename F, int SIZE, int... N>
constexpr std::array<T, SIZE>
genarray(F f) {
return std::array<T, SIZE>{{ f(N)... }};
}
template<typename T, typename F, int SIZE, int...> struct recursive_gen;
template<typename T, typename F, int SIZE, int... Args>
struct recursive_gen<T, F, SIZE, 0, Args...> {
static constexpr std::array<T, SIZE> generate(F f) {
return genarray<T, F, SIZE, 0, Args...>(f);
}
};
template<typename T, typename F, int SIZE, int N, int... Args>
struct recursive_gen<T, F, SIZE, N, Args...> {
static constexpr std::array<T, SIZE> generate(F f) {
return recursive_gen<T, F, SIZE, N - 1, N, Args...>::generate(f);
}
};
template<typename T, int SIZE>
struct array_generator {
template<typename F>
static constexpr std::array<T, SIZE> generate(F f) {
return recursive_gen<T, F, SIZE, SIZE - 1>::generate(f);
}
};
std::array<double, 4> const A = array_generator<double, 4>::generate([](int i) { return std::sin(0.1 * i);});
std::array<double, 4> const B = array_generator<double, 4>::generate([](int i) { return std::cos(0.1 * i);});
constexpr int fun(int i) { return 2 * i; }
constexpr std::array<int, 4> const C = array_generator<int, 4>::generate(fun); // generation during compile time
LIVE DEMO
Note however, that in order for generation to take place at compile time input function in array_generator must be constexpr. This is not the case for trigonometric functions (i.e., they are not constexpr). Thus initialization of arrays A and B will take place at initialization time, whereas generation of array C will take place at compile time.
Imagine that global array A is much longer and you don't want to do all of this repetitive typing. Is there a shorter way to initialize array A at compile or initialization time
Create a generator and pass it through std::generate_n() (or plain std::generate()).
#include <algorithm>
#include <array>
#include <cmath>
template <typename Value_t>
struct SinGenerator{
SinGenerator(std::size_t start = 0, Value_t counter_scalar = 1)
: index{start},
scalar{counter_scalar} {
}
Value_t operator()() {
return sin(index++ * scalar);
}
std::size_t index;
Value_t scalar;
};
template <typename Value_t, std::size_t Size>
std::array<Value_t, Size> init_table(const std::size_t start,
const Value_t counter_scalar) {
std::array<Value_t, Size> arr;
SinGenerator<Value_t> gen(start, counter_scalar);
std::generate(arr.begin(), arr.end(), gen);
return arr;
}
const auto kSinTable(init_table<float, 10>(0, 0.1f));
In case you A array will always stays the same and is very big, you can always write a short script, which calculates every value in array and output could be used in source code to have static initialization.
In case formula is simple, even MS Excel could be used to generate that kind of static initialization data.
Let's imagine I have several template functions, e.g.:
template <int I> void f();
template <int I> void g();
template <int I> void h();
How can I call sequence of any of these functions for sequence of template parameters?
In other words, I need such behaviour:
{some template magic}<1, 5>(f); // This is pseudocode, I don't need exactly this format of calling.
unrolls into:
f<1>();
f<2>();
f<3>();
f<4>();
f<5>();
And I need the same method to work for every of my functions (not only for f, but for g and h too) without writing big awkward structure for every of these functions.
I can use C++11, and even already implemented in latest development gcc version C++1y/C++14 functionality (http://gcc.gnu.org/projects/cxx1y.html), e.g. polymorphic lambdas.
With C++1y features. Instead of calling the function directly and passing the template argument as, well, a template argument, you can create a lambda that takes a function argument which contains the template argument as part of its type. I.e.
f<42>();
[](std::integral_constant<int, 42> x) { f<x.value>(); }
[](auto x) { f<x.value>(); }
With this idea, we can pass the function template f around, when wrapped into such a polymorphic lambda. That's possible for any kind of overload set, one of the things you can't do with ordinary lambdas.
To call f with a sequence of template arguments, we'll need the common indices classes for the indices expansion trick. Those will be in the C++1y Standard Library. Coliru's clang++ compiler for example still uses an older libstdc++ which doesn't have them AFAIK. But we can write our own:
#include <utility>
using std::integral_constant;
using std::integer_sequence; // C++1y StdLib
using std::make_integer_sequence; // C++1y StdLib
// C++11 implementation of those two C++1y StdLib classes:
/*
template<class T, int...> struct integer_sequence {};
template<class T, int N, int... Is>
struct make_integer_sequence : make_integer_sequence<T, N-1, N-1, Is...> {};
template<class T, int... Is>
struct make_integer_sequence<T, 0, Is...> : integer_sequence<T, Is...> {};
*/
When we write make_integer_sequence<int, 5>, we'll get a type that's derived from integer_sequence<int, 0, 1, 2, 3, 4>. From the latter type, we can deduce the indices:
template<int... Indices> void example(integer_sequence<int, Indices...>);
Inside this function, we have access to the indices as a parameter pack. We'll use the indices to call the lamba / function object f as follows (not the function template f from the question):
f( integral_constant<int, Indices>{} )...
// i.e.
f( integral_constant<int, 0>{} ),
f( integral_constant<int, 1>{} ),
f( integral_constant<int, 2>{} ),
// and so on
Parameter packs can only be expanded in certain contexts. Typically, you'd expand the pack as initializers (e.g. of a dummy array), as the evaluation of those is are guaranteed to be ordered (thanks, Johannes Schaub). Instead of an array, one could use a class type such as
struct expand { constexpr expand(...) {} };
// usage:
expand { pattern... };
A dummy array looks like this:
int expand[] = { pattern... };
(void)expand; // silence compiler warning: `expand` not used
Another tricky part is to deal with functions returning void as the pattern. If we combine a function call with a comma operator, we always get a result
(f(argument), 0) // always has type int and value 0
To break any existing overloaded comma operators, add a void()
(f(argument), void(), 0)
Finally, combine all the above to create magic:
template<int beg, class F, int... Is>
constexpr void magic(F f, integer_sequence<int, Is...>)
{
int expand[] = { (f(integral_constant<int, beg+Is>{}), void(), 0)... };
(void)expand;
}
template<int beg, int end, class F>
constexpr auto magic(F f)
{
// v~~~~~~~v see below (*)
return magic<beg>(f, make_integer_sequence<int, end-beg+1>{});
}
Usage example:
#include <iostream>
template<int N> void f() { std::cout << N << "\n"; }
int main()
{
//magic<1, 5>( [](auto x) { f<decltype(x)::value>(); } );
magic<1, 5>( [](auto x) { f<x.value>(); } );
}
(*) IMHO end-beg+1 is bad practice. There's a reason why the StdLib works with half-open ranges of the form [begin, end): The empty range simply is [begin, begin). With the StdLib using half-open ranges, it might be inconsistent to use closed ranges here. (There's one exception in the StdLib I know of, it has to do with PRNGs and the maximum integer value.)
I'd suggest you'd design your magic interface to take half-open ranges, i.e.
magic<1, 6>( [](auto x) { f<x.value>(); } ); // [1, 6) i.e. {1,2,3,4,5}
with the implementation
template<int beg, int end, class F>
constexpr auto magic(F f)
{
// v~~~~~v
return magic<beg>(f, make_integer_sequence<int, end-beg>{});
}
Note the weird +1 disappears.
Using reified functions and template template arguments:
#include <iostream>
template<int I> class f {
public:
static void call() {
std::cout << I << '\n';
}
};
template<template<int I> class X, int I, int J> class magic {
public:
static void call() {
X<I>::call();
magic::call();
}
};
template<template<int I> class X, int I> class magic<X,I,I> {
public:
static void call() {
X<I>::call();
}
};
int main(int argc, char** argv) {
magic<f,2,6>::call();
return 0;
}