Check sizes are the same when compiling - c++

I have a dictionary and an array neither of which change size during the program but could often be extended pre compilation. The number of keys and the array length should always be the same size. Is there a way to check this when compiling as it'd be easy to add the key but not to the array or visa versa?

There are ways to check compile time constants. In C++11 it has been cemented with static_assert but it's possible with templates as well.
For example given:
enum Key {
K_Zero,
K_One,
K_Two,
K_NUMBER_ELEMENTS
};
static char const Dictionary[] = { ... };
You would do it C++11:
static_assert(K_NUMBER_ELEMENTS == ARRAY_SIZE(Dictionary),
"Keys / Dictionary mismatch");
Where ARRAY_SIZE is defined as:
template <typename T, unsigned N>
char (&ComputeArraySize(T (&)[N]))[N];
#define ARRAY_SIZE(Array) sizeof(ComputeArraySize(Array))
If you are still in C++03 (which is probably the case if you don't know the version), then you ought to be a little more clever and replace the static_assert with:
template <unsigned M, unsigned N> struct mp_equal;
template <unsigned N> struct mp_equal<N,N> {};
namespace {
mp_equal<K_NUMBER_ELEMENTS, ARRAY_SIZE(Dictionary)>
AssertKeysAndDictionarySizeMatch = {};
}
Which will trigger a compile time error if they do not match.

Assuming by dictionary you mean map or unordered_map there's no immediate way to do it at compile time. You could runtime assert in main OR you could force the map to be always initialized from an array of pairs, and then static_assert that the length of the pair array is the same as your main array.

Related

Constexpr: Convert a list of string views into a list of char arrays

I came across an interesting constexpr problem that haven't been able to fully crack. The last piece of the puzzle that I'm missing is the following
// Given a constexpr array of string views
constexpr std::array<std::string_view, X> views = ...;
// Convert it to a list of char arrays
constexpr std::tuple<std::array<char, Xs>...> buffers = ...;
My problem here is finding the right size for each array. How can I extract the sizes of the string_views in views and pass them as template parameters to another function?
I could just use the same size for every buffer, big enough to hold every argument, but I'm wondering if there is a way of optimizing their sizes since the info is known at compile time.
Full description of the problem I'm trying to solve.
(in case someone can come up with a better approach, also cause I think it's interesting...)
I want to create a macro that converts a list of arguments into a list of name-value pairs. For instance
// Adding types explicitly to show what I want to achieve.
int x;
float y;
double z;
using named_values_t = std::tuple<
std::pair<const char*, int&>,
std::pair<const char*, float&>,
std::pair<const char*, double&>>;
named_values_t nv = MY_MACRO(x, y, z);
The const char* adds significant difficulty but it's a requirement for a third-party lib.
Now I know that can be done with Boost.Preprocessor but I'd like to do it just using the STL and constexpr methods to avoid adding boost just for this. Also I know this would be trivial on a compiler with support for constexpr std::string but I'm using C++17.
The string processing can be easily done with constexpr functions,
// Split "one, two, three" into {"one", "two", "three"}.
template <size_t Count>
constexpr std::array<std::string_view, Count> split_arguments(std::string_view);
However, I cannot pass these string_views directly as char pointers, since at this point they're just pointers to a bigger array in memory (the complete "one, two, three"). To pass as const char* each element needs to be null-terminated.
But we can build an std::array for each std::string_view and copy its contents, this way we have a char array for each argument name, that will generate a null-terminated segment of memory for each name.
constexpr std::string_view args = "one, two, three";
constexpr std::array<std::string_view, 3> views = split_arguments<3>(args); // {"one", "two", "three"}
constexpr std::tuple<std::array<char, Xs>...> buffers = make_buffers<Xs...>(views);
Here I'm not able to figure out how pass the lengths of the views as template arguments to the next function.
Working solution here (using bigger fixed-sized buffers): https://gcc.godbolt.org/z/WKsbvb
The fixed-size buffer solution is ok, but it would be great to go that extra step to fit the buffers to their actual size.
So long as views is a variable with static storage duration (rather than a prvalue created by a constexpr function call), you can implement this with the usual auto& template parameter and std::index_sequence tricks:
#include<array>
#include<string_view>
#include<tuple>
#include<utility>
#include<type_traits>
#include<cstddef>
namespace detail {
template<std::size_t N>
constexpr auto copy_string(std::string_view s) {
std::array<char,N+1> ret{}; // zero-initialize
for(std::size_t i=N;i--;) ret[i]=s[i];
return ret;
}
template<auto &V,std::size_t ...II>
constexpr auto buffers(std::index_sequence<II...>) {
return std::make_tuple(copy_string<V[II].size()>(V[II])...);
}
}
template<auto &V> constexpr auto buffers=
detail::buffers<V>
(std::make_index_sequence
<std::tuple_size_v<std::remove_reference_t<decltype(V)>>>());
constexpr std::array<std::string_view, 3> views = {"C","++",""};
static_assert(std::is_same_v
<decltype(buffers<views>),
const std::tuple<std::array<char,2>,
std::array<char,3>,
std::array<char,1>>>);
static_assert(std::get<0>(buffers<views>)[0]=='C');
static_assert(std::get<1>(buffers<views>)[1]=='+');
static_assert(std::get<2>(buffers<views>)[0]=='\0');

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>>;

Q: Generate argument list at compile time

I'm trying to create some tuple at compile time, just a type and a bitset (which represent the type for some operations).
I want something like:
<Foo1,0x001>, <Foo2,0x002>, <Foo3,0x003>...
That's why I have a Metadata struct:
template < typename T,
size_t Size >
struct Metadata {
using type = T;
std::bitset<Size> bitset;
};
And, thanks to everyone, the make function is something like that:
template <typename...Ts,typename...Args>
constexpr auto make_metadata(Args... args)
{
constexpr auto N = sizeof...(Ts);
return std::make_tuple(Metadata<Ts, N>{args}...);
}
But I need to give it the bitset value right now. And I know the bitset value at compile time as I said at the beginning. So how could I generate an argument list like (0,1,2,...,N - 1) ?
With C++14, you can use std::integer_sequence and std::make_integer_sequence() to generate a compile-time parameter pack of monotonically increasing integers, which should work in your use case.

Populate An Array Using Constexpr at Compile-time

I would like to populate an array of enum using constexpr.
The content of the array follows a certain pattern.
I have an enum separating ASCII character set into four categories.
enum Type {
Alphabet,
Number,
Symbol,
Other,
};
constexpr Type table[128] = /* blah blah */;
I would like to have an array of 128 Type. They can be in a structure.
The index of the array will be corresponding to the ASCII characters and the value will be the Type of each character.
So I can query this array to find out which category an ASCII character belongs to. Something like
char c = RandomFunction();
if (table[c] == Alphabet)
DoSomething();
I would like to know if this is possible without some lengthy macro hacks.
Currently, I initialize the table by doing the following.
constexpr bool IsAlphabet (char c) {
return ((c >= 0x41 && c <= 0x5A) ||
(c >= 0x61 && c <= 0x7A));
}
constexpr bool IsNumber (char c) { /* blah blah */ }
constexpr bool IsSymbol (char c) { /* blah blah */ }
constexpr Type whichCategory (char c) { /* blah blah */ }
constexpr Type table[128] = { INITIALIZE };
where INITIALIZE is the entry point of some very lengthy macro hacks.
Something like
#define INITIALIZE INIT(0)
#define INIT(N) INIT_##N
#define INIT_0 whichCategory(0), INIT_1
#define INIT_1 whichCategory(1), INIT_2
//...
#define INIT_127 whichCategory(127)
I would like a way to populate this array or a structure containing the array without the need for this macro hack...
Maybe something like
struct Table {
Type _[128];
};
constexpr Table table = MagicFunction();
So, the question is how to write this MagicFunction?
Note: I am aware of cctype and likes, this question is more of a Is this possible? rather than Is this the best way to do it?.
Any help would be appreciated.
Thanks,
Ignoring ALL the issues, indices to the rescue:
template<unsigned... Is> struct seq{};
template<unsigned N, unsigned... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>{};
template<unsigned... Is>
struct gen_seq<0, Is...> : seq<Is...>{};
template<unsigned... Is>
constexpr Table MagicFunction(seq<Is...>){
return {{ whichCategory(Is)... }};
}
constexpr Table MagicFunction(){
return MagicFunction(gen_seq<128>{});
}
Live example.
In C++17 ::std::array has been updated to be more constexpr friendly and you can do the same as in C++14, but without some of the scary looking hacks to get around the lack of constexpr in crucial places. Here is what the code would look like there:
#include <array>
enum Type {
Alphabet,
Number,
Symbol,
Other,
};
constexpr ::std::array<Type, 128> MagicFunction()
{
using result_t = ::std::array<Type, 128>;
result_t result = {Other};
result[65] = Alphabet;
//....
return result;
}
const ::std::array<Type, 128> table = MagicFunction();
Again MagicFunction still needs to obey the rather loose constexpr rules. Mainly, it may not modify any global variables or use new (which implies modifying global state, namely the heap) or other such things.
IMHO the best way to do this is simply write a tiny setup program that will generate table for you. And then you can either throw out the setup program, or check it in alongside the generated source code.
The tricky part of this question is just a duplicate of this other one: Is it possible to create and initialize an array of values using template metaprogramming?
The trick is, it's impossible to write anything like
Type table[256] = some_expression();
at file scope, because global arrays can be initialized only with literal (source-level) initializer-lists. You can't initialize a global array with the result of a constexpr function, even if you could somehow get that function to return a std::initializer_list, which you can't because its constructor isn't declared constexpr.
So what you have to do is get the compiler to generate the array for you, by making it a static const data member of a template class. After one or two levels of metaprogramming that I'm too confused to write out, you'll bottom out in a line that looks something like
template <int... Indices>
Type DummyStruct<Indices...>::table[] = { whichCategory(Indices)... };
where Indices is a parameter-pack that looks like 0,1,2,... 254,255. You construct that parameter-pack using a recursive helper template, or maybe just using something out of Boost. And then you can write
constexpr Type (&table)[] = IndexHelperTemplate<256>::table;
...But why would you do all that, when the table is only 256 entries that will never change unless ASCII itself changes? The right way is the simplest way: precompute all 256 entries and write out the table explicitly, with no templates, constexpr, or any other magic.
The way to do this in C++14 looks like this:
#include <array>
enum Type {
Alphabet,
Number,
Symbol,
Other,
};
constexpr ::std::array<Type, 128> MagicFunction()
{
using result_t = ::std::array<Type, 128>;
result_t result = {Other};
const result_t &fake_const_result = result;
const_cast<result_t::reference>(fake_const_result[65]) = Alphabet;
//....
return result;
}
const ::std::array<Type, 128> table = MagicFunction();
No clever template hackery required any longer. Though, because C++14 didn't really undergo a thorough enough review of what did and didn't have to be constexpr in the standard library, a horrible hack involving const_cast has to be used.
And, of course, MagicFunction had better not modify any global variables or otherwise violate the constexpr rules. But those rules are pretty liberal nowadays. You can, for example, modify all the local variables you want, though passing them by reference or taking their addresses may not work out so well.
See my other answer for C++17, which allows you to drop some of the ugly-looking hacks.

How can the allowed range of an integer be restricted with compile time errors?

I would like to create a type that is an integer value, but with a restricted range.
Attempting to create an instance of this type with a value outside the allowable range should cause a compile time error.
I have found examples that allow compile time errors to be triggered when an enumeration value outside those specified is used, but none that allow a restricted range of integers (without names).
Is this possible?
Yes but it's clunky:
// Defining as template but the main class can have the range hard-coded
template <int Min, int Max>
class limited_int {
private:
limited_int(int i) : value_(i) {}
int value_;
public:
template <int Val> // This needs to be a template for compile time errors
static limited_int make_limited() {
static_assert(Val >= Min && Val <= Max, "Bad! Bad value.");
// If you don't have static_assert upgrade your compiler or use:
//typedef char assert_in_range[Val >= Min && Val <= Max];
return Val;
}
int value() const { return value_; }
};
typedef limited_int<0, 9> digit;
int main(int argc, const char**)
{
// Error can't create directly (ctor is private)
//digit d0 = 5;
// OK
digit d1 = digit::make_limited<5>();
// Compilation error, out of range (can't create zero sized array)
//digit d2 = digit::make_limited<10>();
// Error, can't determine at compile time if argc is in range
//digit d3 = digit::make_limited<argc>();
}
Things will be much easier when C++0x is out with constexpr, static_assert and user defined literals.
Might be able to do something similar by combining macros and C++0x's static assert.
#define SET_CHECK(a,b) { static_assert(b>3 && b<7); a=b; }
A runtime integer's value can only be checked at runtime, since it only exists at runtime, but if you make a runtime check on all writing methods, you can guarantee it's contents. You can build a regular integral replacement class with given restrictions for that.
For constant integers, you could use a template to enforce such a thing.
template<bool cond, typename truetype> struct enable_if {
};
template<typename truetype> struct enable_if<true, truetype> {
typedef truetype type;
};
class RestrictedInt {
int value;
RestrictedInt(int N)
: value(N) {
}
public:
template<int N> static typename enable_if< (N > lowerbound) && (N < upperbound), RestrictedInt>::type Create() {
return RestrictedInt(N);
}
};
Attempting to create this class with a template value that isn't within the range will cause a substitution failure and a compile-time error. Of course, it will still require adornment with operators et al to replace int, and if you want to compile-time guarantee other operations, you will have to provide static functions for them (there are easier ways to guarantee compile-time arithmetic).
Well, as you noticed, there is already a form of diagnostic for enumerations.
It's generally crude: ie the checking is "loose", but could provide a crude form of check as well.
enum Range { Min = 0, Max = 31 };
You can generally assign (without complaint) any values between the minimal and maximal values defined.
You can in fact often assign a bit more (I think gcc works with powers of 2).