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.
Related
Weird question but let me explain. I'm creating a Deserializer that needs to have specialized functions for Deserializing different types, including primitives, arrays, and vectors. An example of this is the integral function, which looks like this:
/** Reads an integral. */
template<typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
inline T read() {
ind += sizeof(T);
return reinterpret_cast<T>(data[ind - sizeof(T)]);
}
When I tried to add vector support, I ran into a problem. Ideally, I'd like to write a specialization for vectors containing integral types, and I initially thought I could do it like this:
/** Reads a vector of integrals. */
template<typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
inline std::vector<T> read() {
usize len = read<size_t>();
auto startInd = ind;
ind += len * sizeof(T);
return std::vector<T>(
reinterpret_cast<const T*>(&data[startInd]),
reinterpret_cast<const T*>(&data[ind]));
}
but then a problem occurs where trying to read a vector of int has the same signature as trying to read a single int, read<int>().
To fix this, I want to make it so that the vector signature looks like this: read<std::vector<int>>(), but I can't figure out how to do this. Is there a way to require the vector type in the template argument, but still get the inner type it uses for use in the function?
Thanks!!
Yes, you can suppose std::vector as the template parameter, and get the element type from std::vector::value_type. E.g.
template<typename V, std::enable_if_t<std::is_integral<typename V::value_type>::value, bool> = true>
// ^^^^^^^^^^^^^^^^^^^^^^ check the element type
inline V read() {
using T = typename V::value_type; // get the element type
...
}
Then you can call it as read<std::vector<int>>().
BTW: This doesn't only work for std::vector, but also other containers having nested type value_type which is integral type.
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>>;
Say I have a variable amount of arguments which I want to multiply together. The first way I think of is a recursive algorithm:
template<typename Head>
u64 Multiply(Head head) const
{
return head;
}
template<typename Head, typename... Tail>
u64 Multiply(Head head, Tail... tail) const
{
return head * Multiply(tail...);
}
But then I saw this trick:
// u32 and u64 are 32 and 64 bit unsigned integers.
template<typename... T>
u64 Multiply(T... args)
{
u64 res = 1;
for (const u32& arg: {args...})
res *= arg;
return res;
}
The second one appears way nicer to me. Easier to read. However, how does this act on performance? Is anything being copied? What does {args...} do in the first place? Is there a better method?
I have access to C++14.
Edit to be clear: It is about run time multiplication, not compile time.
More to be clear: I do not want to compute integers necessarily(although that is my current application), but the algorithm that I found was specialized for integers.
More: Arguments are of the same type. Algorithms without this restriction would be very interesting but maybe for a different question.
There are multiple questions asked here:
What's the impact on performance? Dunno. You'll need to measure. Depending on the type of the arguments I can imagine that the compiler entirely optimizes things either way, though: it does know the number of arguments and the types.
What is { args... }? Well, it creates an std::initializer_list<T> for the common type of the arguments (assuming there is one). You may want to use the value with std::common_type_t<T...> instead of a fixed type, though.
Is there a better method? There are a couple of approaches although I could imagine that the compiler actually does rather well with this expansion. The alternative which immediately comes to mind is return (args * ... * 1); which, however, requires C++17. If there is at least one argument the * 1 can be omitted: it is there to avoid a compile-time error if there is an empty list of variadic parameters.
The code
template<typename... T>
u64 Multiply(T... args)
{
u64 res = 1;
for (const u32& size : {args...})
res *= size;
return res;
}
is a bit mysterious to me :-) Why we have template parameters with type T and inside the method we used fix size values? And the variable name size looks very obscure because this var has nothing to do with any kind of size. And using integer types inside is also not a valid assumption if you give floating point data into the template.
OK, but to answer your question:
The first one can be used with all types you put into the template function. The second one used fixed ( unsigned integer ) types, which is not what I expect if I see the declaration of the template itself.
Both version can be made constexpr as I learned now :-) and work pretty well for compile time calculation.
To answer the question from your comment:
{args...}
expands to:
{ 1,2,3,4}
which is simply an "array" ( std::std::initializer_list) and only works if all elements have the same type.
So having
for (const u32& size : {args...})
simply iterates over the array.
I am designing a C++ library that reads a CSV file of reported data from some experiment and does some aggregation and outputs a pgfplots code. I want to make the library as generic and easy to use as possible. I also want to isolate it from the data types that are represented in the CSV file and leave the option to user to parse each column as she desires. I also want to avoid Boost Spirit Qi or other heavy duty parser.
The simple solution I have is for the user to create a type for each column, with a constructor that takes "char *". The constructor does its own parsing for the value it is given, which is one cell from the data. The user then passes me a list of types; the schema, representing the types in a line of data. I use this type list to create a tuple, in which every member of the tuple is responsible for parsing itself.
The problem now is how to initialise (construct) this tuple. Dealing with tuples is of course not straightforward since iterating over their elements is mostly a compile-time operation. I used Boost Fusion at first to achieve this task. However, the function I used (transform) although might take a tuple as input (with the appropriate adapter), it does not seem to return a tuple. I need the return value to be a tuple so some other code can use it as an associative type-to-value container (access it by type via std::get<T>), while using only standard tools, that is, without using Boost. So I had to convert whatever Fusion's transform returned into std::tuple.
My question is how to avoid this conversion, and better yet how to avoid Boost Fusion completely.
A simple solution that comes to mind is to use the constructor of std::tuple, and somehow pass each element its respective "const *" that it needs to construct. However, while this is possible using some complicated template-based enumeration techniques, I am wondering if there is a straightforward "parameter-pack"-like approach, or an even simpler way to pass the values to the constructors of the individual elements of a tuple.
To clarify what I am seeking, kindly take a look at this following code.
#include <cstdio>
#include <array>
template <typename...> struct format {};
template <typename...> struct file_loader {};
template <typename... Format>
struct
file_loader<format<Format...> > {
void load_file() {
size_t strsize = 500u;
char *str = new char[strsize]();
auto is = fopen("RESULT","r");
/* example of RESULT:
dataset2,0.1004,524288
dataset1,0.3253,4194304
*/
while(getline(&str, &strsize, is) >= 0) {
std::array<char*, 3> toks{};
auto s = str;
int i = 2;
while(i --> 0)
toks[i] = strsep (&s, ",");
toks[2] = strsep (&s, ",\n");
std::tuple<Format...> the_line{ /* toks */ } ; // <-- HERE
//// current solution:
// auto the_line{
// as_std_tuple( // <-- unnecessary conversion I'd like to avoid
// boost::fusion::transform(boost::fusion::zip(types, toks), boost::fusion::make_fused( CAST() ))
// )};
// do something with the_line
}
}
};
#include <string>
class double_type {
public:
double_type() {}
double_type(char const *token) { } // strtod
};
class int_type {
public:
int_type() {}
int_type(char const *token) { } // strtoul
};
int main(int argc, char *argv[]) {
file_loader< format< std::string,
double_type,
int_type > >
{}.load_file();
return 0;
}
I've highlighted the interesting line as "HERE" in a comment.
My question precisely is:
Is there a way to construct a std::tuple instance (of heterogeneous
types, each of which is implicitly convertible from "char *") with
automatic storage duration (on the stack) from a std::array<char *, N>,
where N equals the size of that tuple?
The answer I am seeking should
Avoid Boost Fusion
(Simplicity condition) Avoid using more than 5 lines of boilerplate template-based enumeration code
Alternatively, shows why this is not possible to do in the C++14 standard
The answer can use C++17 constructs, I wouldn't mind.
Thank you,
As with all questions involving std::tuple, use index_sequence to give you a parameter pack to index the array with:
template <class... Formats, size_t N, size_t... Is>
std::tuple<Formats...> as_tuple(std::array<char*, N> const& arr,
std::index_sequence<Is...>)
{
return std::make_tuple(Formats{arr[Is]}...);
}
template <class... Formats, size_t N,
class = std::enable_if_t<(N == sizeof...(Formats))>>
std::tuple<Formats...> as_tuple(std::array<char*, N> const& arr)
{
return as_tuple<Formats...>(arr, std::make_index_sequence<N>{});
}
Which you would use as:
std::tuple<Format...> the_line = as_tuple<Format...>(toks);
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.