Compile-time search in static-array - c++

In a project, I have several classes which encapsulate, among other things, matrices implemented as static-arrays, e.g.:
struct StaticContainer
{
static const short e[2][4];
};
/// Initialize components of member-array (with external linkage).
const short StaticContainer::e[2][4] = {
{ -1, 0, 0, 1 },
{ 0, -1, 1, 0 }
};
I would like to implement a meta-function which provides the inverse-mapping, from a column in StaticContainer::e back to the second index (1-4 in this case). Ideally, something like this:
template< typename TContainer, short TeX, short TeY >
struct VectorToIndex
{
enum { value = ??? };
};
Finally, I would like to pass (if this is possible at all):
BOOST_STATIC_ASSERT( 0 == VectorToIndex< StaticContainer, -1, 0 >::value );
Is this possible at all? My initial attempts to recursively-search through the 'e'-matrix failed, because whenever I try to access (at compile-time) the entries within I get (GCC):
error: ‘StaticContainer::e’ cannot appear in a constant-expression
Shall I understand that the values in the matrix are not available at compile-time?
I would appreciate any comments. I am free to change the way the matrix is initialized/stored (so I was thinking of some compile-time registration mechanism). The only constraint is to get this inverse-mapping at compile-time.
Clarifications:
Each column in the e-matrix represents a spatial direction (in this case, 2D). The columns are guaranteed to be distinct.
I would expect the following results from the meta-function:
VectorToIndex< StaticContainer, -1, 0 > --> '0' at compile-time
VectorToIndex< StaticContainer, 0,-1 > --> '1' at compile-time
VectorToIndex< StaticContainer, 0, 1 > --> '2' at compile-time
VectorToIndex< StaticContainer, 1, 0 > --> '3' at compile-time
If this template is instantiated with an invalid combination of numbers (i.e. which is not a column in the matrix), I would like to produce a compilation-error.
The solution I currently have is a simple program which writes files with the necessary template-instantiations manually. This satisfies the requirements (results are correct and for invalid vectors there is a compile-time error - since the corresponding template-instantiation is missing). However, since I have many classes similar to 'StaticContainer' in my codebase (many of them with larger matrices), this process generates thousands of lines of code :(.

As promissed, here goes a solution. Rather than reinventing a whole metaprogramming library using variadic templates, I used this opportunity to try out boost mpl and it turns out to be pretty expressive. Using it, VectorToIndex would look like the following:
template<typename basis, typename axis>
struct VectorToIndex :
boost::mpl::if_<
boost::mpl::greater<boost::mpl::size<basis>, typename boost::mpl::find<basis, axis>::type::pos>,
typename boost::mpl::find<basis, axis>::type::pos,
boost::mpl::empty_base
>::type
{
};
If "axis" is present in "basis" then VectorToIndex<basis, axis>::value equals its index in the range [0, size-of-basis). If otherwise this is not true, than VectorToIndex<basis, axis>::value is not defined, thus accessing it may be used to produce compile-time errors or
selective instanciation through SFINAE.
To represent the axis one should use boost::mpl::vector, like shown below:
typedef boost::mpl::vector<boost::mpl::int_<1>, boost::mpl::int_<0>, boost::mpl::int_<0> > e1;
typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<1>, boost::mpl::int_<0> > e2;
typedef boost::mpl::vector<boost::mpl::int_<0>, boost::mpl::int_<0>, boost::mpl::int_<1> > e3;
Considering the definitions above, one has
VectorToIndex<boost::mpl::vector<e1, e2, e3>, e1>::value -> 0
VectorToIndex<boost::mpl::vector<e1, e2, e3>, e2>::value -> 1
VectorToIndex<boost::mpl::vector<e1, e2, e3>, e3>::value -> 2
VectorToIndex<boost::mpl::vector<e1, e2>, e3>::value -> COMPILE-TIME ERROR

There is a mismatch in your declarations:
typename TContainer means that the template parameter is a type
StaticContainer::e is a value
It cannot match.
There are a few potential solutions I can think of, but the first question is obviously: why not build the reverse matrix manually and use assert to prove its correctness ? It is certainly simpler, and simple is beautiful.

Related

Macro for nested maps in C++

Is it possible to create simple interface to create nested std::maps in C++? If this is possbile, can I go advanced and make it with different nested maps/vectors
CreateMaps(4); returns std::map<int,std::map<int,std::map<int,std::map<int,int>>>>>
CreateMaps(3); returns std::map<int,std::map<int,std::map<int,int>>>>
I am not really sure if this counts as macro or no.
My final target is to create maps at init and I want to divide into categories, type_0 has X subtypes which has Y subtypes and so on..., and I want to count how many times I reach certain scenario. Creating the map is defined after parsing a file, so I dont know the size and the number of nested maps at compile time.
Yes you can, even without macros, but by using recursive templates. Here is what it could look like:
// Recursive definition
template<typename T, size_t N>
struct NestedMap {
using type = std::map<T, typename NestedMap<T, N - 1>::type>;
};
// Termination condition for the recursion
template<typename T>
struct NestedMap<T, 0> {
using type = T;
};
// Just a convenience
template<typename T, size_t N>
using NestedMap_t = NestedMap<T, N>::type;
And then you can use it like so:
NestedMap_t<int, 4> quadmap;
quadmap[1][2][3][4] = 42;
However, nesting containers is often not very efficient, and you might get better performance by flattening your data structure. If you want to have a map that is indexed by four integers, then you could also do:
std::map<std::array<int, 4>, int> quadmap;
quadmap[{1, 2, 3, 4}] = 42;
The above types are fixed at compile time. If you want something more flexible, you should make the map's key and value more dynamic. Consider:
std::map<std::vector<int>, std::any> anymap;
anymap[{1, 2, 3, 4}] = 42;

Compile-Time Creation of Array of Templated Objects in High Level Synthesis

I'm trying to accomplish this with HLS, not with "normal" C++, so most libraries (STL, boost, etc.) won't work as they can't be synthesized (manual memory management is not allowed). I think this should be possible with template metaprogramming, but I'm a little stuck.
I want to create an array of shift registers, each with a variable depth. I have N inputs, and I want to create N shift registers, with depths 1 to N, where N is known at compile time. My shift register class basically looks like
template<int DEPTH>
class shift_register{
int registers[DEPTH];
...
};
I tried following this and adapting it: Programmatically create static arrays at compile time in C++ , however, the issue is with the last line. Each templated shift register is going to be a different type, and so can't be put together in an array. But I do need an array, as there wouldn't be a way to access each shift register.
Any help would be appreciated!
Just to clarify, my problem was the following: generate N shift_registers, templated from 1 to N, where N is a compile time constant.
For example, if I had N=4, I could easily write this as:
shift_register<1> sr1;
shift_register<2> sr2;
shift_register<3> sr3;
shift_register<4> sr4;
But this wouldn't be easy to change, if I wanted a different value for N in the future.
I ended up using the preprocessor and took the solution from here: How do I write a recursive for-loop "repeat" macro to generate C code with the CPP preprocessor?
I used the macros from that solution like this:
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define BODY(i) shift_register<i> CAT(sr,i)
REPEAT_ADD_ONE(BODY, N, 1);
And then something similar to that in order to access the shift registers, in a sort of array fashion.
This let me achieve the compile time generation that I was looking for, and get the array type access I needed.
Your question was somewhat difficult to understand but I'll do my best...
template <typename ... Args>
constexpr auto make_array(Args && ... pArgs)
{
using type = std::common_type_t<std::decay_t<Args>...>;
return std::array<type, sizeof...(Args)>{ (type)pArgs ... };
}
Then use it like this:
auto constexpr var_array_of_arrays = std::make_tuple
(
make_array(1, 2, 3, 3),
make_array(2, 3, 4),
make_array(1, 2, 3 ,4 ,3, 5)
);
To get the M'th element you access it like this, n has to actually be a compile-time constant:
std::get<M>(var_array_of_arrays);
To access the Nth element in the Mth array:
auto constexpr value = std::get<M>(var_array_of_arrays)[N]
An to improve the interface:
template <size_t M, size_t N, typename T >
constexpr decltype(auto) get_element(T && pInput)
{
return std::get<M>(std::forward<T>(pInput))[N];
}
Used like this:
auto constexpr element0_1 = get_element<0, 1>(var_array_of_arrays);
This will allow you to use an array of variable length arrays, or atleast something that behaves like that and is identical to that in memory.
A full example is here:
Online compiler
Whenever I hear "compile time number sequence" I think std::index_sequence
namespace detail {
template <typename>
struct shift_registers;
template <std::size_t ... Is> // 0, 1, ... N-1
struct shift_registers<std::index_sequence<Is...> > {
using type = std::tuple<shift_register<Is + 1>...>;
};
template <typename T>
using shift_registers_t = typename shift_registers<T>::type
}
template <std::size_t N>
using shift_registers = detail::shift_registers_t<std::make_index_sequence<N>>;

Trying to sum two compile time tuple integer sequences

If you're keeping track of my question history, I'm updating a dimensional analysis library for the sake of ditching a nightmare of macros and learning C++11, variadic templates, and meta programming and functional programming paradigms. For the life of me, this stuff is still magic.
Anyway, I have tuples of exponent constants that define physical units.
template<int... I>
using make_dimension = std::tuple<std::ratio<I>...>;
using scalar_dimension = make_dimension<0, 0, 0, 0, 0, 0, 0>;
using length_dimension = make_dimension<1, 0, 0, 0, 0, 0, 0>;
using time_dimension = make_dimension<0, 0, 1, 0, 0, 0, 0>;
This is (part) of a library that models the SI units. You can only multiply unlike units, you can additionally add like units and scalars. These libraries are dandy in that they cause compile time errors if you mix units inappropriately. There are >400 units and most of them are defined in terms of other units. When multiplying units, exponents are added, and when dividing units, exponents are subtracted. So to define velocity, I would love a means of expressing:
using velocity_dimension = divide_dimensions<length_dimension, time_dimension>;
And that should be functionally equivalent to writing:
using velocity_dimension = make_dimension<1, 0, -1, 0, 0, 0, 0>;
I've been Googling, but I just don't know the terminology to land some hits. The closest I've found was a for_each that applies a function to elements of a tuple at runtime... And it's kind of blowing my mind, so I can't quite figure out how to turn it into a compile time iteration over the elements. 'make_dimension' above was explained to me a moment ago and it blew my mind, but I recovered. I'm kind of bugged asking for a handout, so does anyone have any good resources for learning this stuff? I'm having a hard time believing I'm the only one remotely interested in doing this.
#dyp's solution in the comments uses a recursively instantiated template. While that's one of the most general techniques for variadic templates, in this case recursion is probably overkill, as the entire set of transformations can be performed in a single pack expansion that expands two parameter packs simultaneously:
template<template<class, class> class, class, class>
struct tuple_transform; // undefined
template<template<class, class> class Transform, class...Ts, class...Vs>
struct tuple_transform<Transform, std::tuple<Ts...>, std::tuple<Vs...>> {
using type = std::tuple<Transform<Ts, Vs>...>;
};
template<class T, class U>
using divide_dimensions = typename tuple_transform<std::ratio_subtract, T, U>::type;
Note that the above assumes that Transform<T, U> is an alias for the desired resulting type. This matches the behavior of ratio_add etc. - they are alias templates for the resulting std::ratio, so typename ratio_add<...>::type is not necessary.
Demo.
While T.C.s answer is correct you can simply take std::integer_sequence (which is C++ 14 but can be simply implemented) instead of ratio and tuple which (in my opinion) don't really fit und use a constexpr functor for manipulation.
Now your code should look like the following (which I didn't try to compile):
template<int... I>
using make_dimension = std::integer_sequence<int, I...>;
template<class Functor, class Dim1, class Dim2>
struct transfrom;
template<class Functor, int... Dims1, int... Dims2>
struct transform<
Functor,
std::integer_sequence<int, Dims1...>,
std::integer_sequence<int, Dims2...>
> {
static_assert(sizeof...(Dims1)==sizeof...(Dims2), "wrong dimensions");
static constexpr Functor f;
using type=std::integer_sequence<int, f(Dims1,Dims2)...>;
};
struct add {
constexpr int operator()(int l, int r) const { return l+r; }
};
struct sub {
constexpr int operator()(int l, int r) const { return l-r; }
};
template<class T, class U>
using divide_dimensions = typename transform<sub, T, U>::type;
I don't have enough info, but it looks like (1,0,-2,0,0,0,0) would be what you would need for acceleration. The 1 represents meters and the - 2 would represent division by seconds squared just as a negative exponent does in math.

Generating permutations via templates

I'd like a function, or function object, that can generate a permutation of its inputs with the permutation specified at compile time. To be clear, I am not looking to generate all of the permutations, only a specific one. For instance, permute<1,4,3,2>( a, b, c, d ) would return (a,d,c,b). Obviously, it is straightforward to do this with a permutation of a specific length, e.g. 2, like this
#include <boost/tuple.hpp>
template< unsigned a, unsigned b>
struct permute {
template< class T >
boost::tuple< T, T > operator()( T ta, T tb ) {
boost::tuple< T, T > init = boost::make_tuple( ta, tb );
return boost::make_tuple( init.get< a >(), init.get< b >() );
}
};
But, how would I go about doing this for an arbitrary length permuation? Also, is there a cleaner way of writing the above code? Yes, the above code is not restricted to making permutations as permute<2,2>(a,b) is allowed, but I don't see that as a flaw. However, can it be restricted to only allowing actual permutations?
C++0x provides variadic templates, which you should be able to use to handle an arbitrary length permutation. They were added specifically because the current version of C++ doesn't have a clean way of dealing with this kind of problem.

How to avoid infinite recursion in C++ class templates

I have a matrix class with the size determined by template parameters.
template <unsigned cRows, unsigned cCols>
class Matrix {
...
};
My program uses matrices of a few sizes, typically 2x2, 3x3, and 4x4. By setting the matrix size with template parameters rather than run-time parameters allows the compiler to do a lot of inlining and optimization.
But now I need a member function that returns a new matrix that has one fewer row and one fewer column.
Matrix<cRows - 1, cCols - 1> Reduced(unsigned row, unsigned col) const { ... }
The idea is that that it will return a matrix with the specified row and column deleted. In practice, this will only ever be called with a matrix that has at least three rows and three columns, returning a 2x2 at the smallest.
The compiler doesn't see the lower bound, so it gets stuck in an infinite recursion trying to instantiate the templates with ever decreasing sizes. I tried putting two clues in the function itself that these smaller sizes cannot occur:
Matrix<cRows - 1, cCols - 1> Reduced(unsigned row, unsigned col) const {
static_assert(cRows > 1 && cCols > 1);
if (cRows <= 1 || cCols <= 1) throw std::domain_error();
Matrix<cRows - 1, cCols - 1> r;
// ... initialize r ...
return r;
}
Neither the static_assert nor the if-statement seems to be a strong enough clue to the compiler that a 0x0 matrix will never be generated. (Ironically, it does complain about the if-statement having a constant compile-time condition.)
Does anyone have any suggestions on how to avoid this compile-time infinite recursion?
You need to provide a specialization for a Matrix that has no rows or no columns.
E.g.
template<unsigned cRows>
class Matrix< cRows, 0 >
{
Matrix<cRows - 1, 0> Reduced() { return Matrix<cRows - 1, 0>(); }
};
template<unsigned cCols>
class Matrix< 0, cCols >
{
Matrix<0, cCols - 1> Reduced() { return Matrix<0, cCols - 1>(); }
};
template<>
class Matrix< 0, 0 >
{
Matrix<0, 0> Reduced() { return Matrix<0, 0>(); }
};
The issue you have is that attempting to instantiate the Matrix Reduced function with a particular set of template parameters always required instantiating the Matrix template for a different set of parameters (cRows - 1, cCols -1). This recursion has to be stopped somewhere. If you are only ever dealing with square matrices, then you can get away with fewer specializations.
Also, you can could stop the recursion with a completely empty class if you are never going to use, say, a 1x1 matrix, the result of reduce on a 2x2 matrix.
template<>
class Matrix< 1, 1 > {};
You can specify a template specializations for small values of cRows or cCols which does not include that method.
You seem a bit confused about compile time and run time behaviour, and I'm a bit confused by your code, but I think what you want is a specialisation of the template for the values, 0, 0, which terminates the recursion.
If you haven't already got it, I suggest reading
C++ Templates: The Complete Guide by Vandervoorde & Josuttis, which covers this sort of thing in detail.
You need to explicitly specify the behaviour for the case where you want the recursion to end. See this DDJ article for more details. Here is a simple example from the article:
template<int n>
class META_FACTORIAL
{
public:
enum{
RET = n * META_FACTORIAL<n-1>::RET
};
};
template<>
class META_FACTORIAL<0>
{
public:
enum{ RET = 1 };
};
Rather than specializing the entire class to terminate the recursion, another option might be to use boost::enable_if on the function to make it available only when the matrix size is above 2x2.