Duplicate: https://stackoverflow.com/a/61819663/11998382
This should be possible if we know the size of the outer vector at compile time.
You just have to write the c++ variadic-template equivalent of the following python code:
def transpose(rng_of_rng):
return zip(*rng_of_rng)
template <std::size_t N, typename T>
auto transpose(std::span<T, N> rng_rng)
{
return [&] <std::size_t... I>(std::index_sequence<I...>)
{
return ranges::views::zip( rng_rng[I]... );
}(std::make_integer_sequence<std::size_t, N>{});
}
And here it is in action: https://godbolt.org/z/oPdn89qnT
I found barry's answer really useful when trying to convert a vector into a static-extent span.
On second thought, maybe this idea isn't so great because be get out a range of tuples. I'm only working with N=10, but I doubt it would be good to have really big tuple sizes.
Related
Iterating over a tuple is a common question in the C++ world and I know the various ways it can be done - usually with recursion and variadic templates.
The reason is that a tuple usually holds different element types and the only way to correctly handle every type is to have a specific overload that matches this type. then we let the compiler dispatch every element to the correct function using recursion.
My case goes like this: I have a tuple of elements, every element is an instantiation of a template class:
std::tuple<my_class<int>, my_class<string>, my_class<float>>
Also, my_class<T> is a derived class of my_class_base, which isn't a template.
Considering this constraint, is it possible to write an at(tuple_type& tuple, size_t n) function that returns the nth element of the tuple, as a reference to the base class, in O(1) steps?
Then I can write
for (size_t i = 0; i < N; i++){
auto& o = at<my_base_class>(tuple, i);
o.call_base_method(...);
}
Thanks.
You might just using std::apply:
std::apply([](auto&...args){ (args.call_base_method(), ...); }, tuple);
Else to answer your question, you might do something like:
template <std::size_t... Is, typename tuple_type>
my_class_base& at_impl(std::index_sequence<Is...>, tuple_type& tuple, size_t n)
{
my_class_base* bases[] = {&std::get<Is>(tuple)...};
*return bases[n];
}
template <typename tuple_type>
my_class_base& at(tuple_type& tuple, size_t n)
{
auto seq = std::make_index_sequence<std::tuple_size<tuple_type>::value>();
return at_impl(seq, tuple, n);
}
Demo
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>>;
Is it possible to create a "sparse" variable-length 2D array using only variadic templates and std::array? By sparse, I mean that each row could have a variable amount of columns.
Ideally, I'd like to instantiate something like VariableLengthTable<int,2,4,3>() and have it create an array of arrays that would map to something like {{0,1}, {0,1,2,3}, {0,1,2}}. I've seen SO posts that deal with variadic templates to create multidimensional arrays, but they are all symmetrical.
Note that I'm limited to zero-cost abstractions (e.g. std::array) as I'm working with a very memory constricted application.
Yes, this should be possible in principle. Here's a bit to get you started:
template <class T, std::size_t... Dim>
using VariableLengthTable = std::tuple<std::array<T, Dim>...>;
This is a tuple of std::arrays, each with a length specified by one of the template arguments.
Note that because the length of a std::array is part of its type, the first dimension cannot be an array, since its members would need different types. However, std::tuple works nicely. As long as you're willing to use std::get<i> instead of [i], and restrict yourself to compile-time is, you should be good.
If a compile-time i is not enough, you have two options:
One, use VariableLengthTable as above and add a runtime-to-compiletime conversion. Conceptually, something like this switch:
T& get(std::size_t x, std::size_t y)
{
switch (x) {
case 0: return std::get<0>(varLenTable)[y];
case 1: return std::get<1>(varLenTable)[y];
case 2: return std::get<2>(varLenTable)[y];
// and so on
}
}
In reality, you'd probably need to compose this using recursion or inheritance to avoid a compile-time out-of-bounds access. Boost.Preprocessor might help with that.
Two, store all the data in one sequential buffer and index into it at runtime. Something like this:
template <class T, std::size_t... Dim>
class VariableLengthTable
{
static const std::array<std::size_t, sizeof...(Dim)> dims = {{ Dim... }};
static const std::array<std::size_t, sizeof...(Dim)> cumulDims = [](){
std::array<std::size_t, sizeof...(Dim)> result;
result[0] = 0;
for (std::size_t idx = 1; idx < sizeof...(Dim); ++idx) {
result[idx] = result[idx - 1] + dims[idx];
}
return result;
}();
std::array<T, cumulDims[sizeof...(Dim) - 1] + dims[sizeof...(Dim) - 1]> data;
public:
T& get(std::size_t x, std::size_t y)
{
return data[cumulDims[x] + y];
}
};
The code above is to show the principle, not guaranteed to compile as-is.
Is there to templatize the "ints" in the lambda function below in the case that there was a standard container of doubles or floats, etc.? I have searched the world over for help with this. I even asked for the help of my professor who says it is possible but is to cryptic about the answer.
template <typename T>
float mean(T &container)
{
auto sum = std::accumulate(container.begin(), container.end(), 0/*initial value*/,
[](int total, int cur)
{
return total+cur;
}//end of lambda
);//end of accumulate
return static_cast<float>(sum) / container.size(); //to find the mean
}//end of mean
Thanks in advance.
There is typically a way to get the type of the contained data from a container.
For e.g you could replace the ints in that function with T::value_type which should support all containers which expose such a typedef.
This wont work for types such as map but you can specialize for it if you want to support them.
But it seems to me that writing such a function that way may induce loss of data
For example
std::vector<float> vf;
vf.push_back(1.3);
vf.push_back(1.5);
vf.push_back(1.3);
vf.push_back(1.123);
vf.push_back(1.526);
float m=mean(vf);
will always return 1
The answer here >>> compute mean using std::accumulate fails in the Edit part is not really true as if I change vf.push_back(1.3); into vf.push_back(3.3); I'll obtain the wished result.
What's the recommended way to convert a string to an array? I'm looking for something like:
template<class T, size_t N, class V>
std::array<T, N> to_array(const V& v)
{
assert(v.size() == N);
std::array<T, N> d;
std::copy(v.begin(), v.end(), d.data());
return d;
}
Does C++11 or Boost provide something like this? How do others do this? Seems silly having to copy/paste this function myself every time I need it in a project.
That seems fine. There isn't such a thing in C++11, and I don't think there is one in Boost either. If you don't want to paste this all over the place, you can just put it in a header and #include that.
Simply calling:
std::copy(v.begin(), v.end(), d.data());
is The way to convert a string to the array. I don't see any advantage of wrapping this into a dedicated "utility" function.
In addition, unless the compiler optimizes it, the performance may degrade with your function: the data will be copied second time when returning the array.
If you really only want convert string to an array, just use .c_str() (and work on char*). It isn't exactly array<> but may suit your needs.
That's fine, maybe with a minor modification in C++11.
template<class T, size_t N, class V>
std::array<T, N> to_array(const V& v)
{
assert(v.size() == N);
std::array<T, N> d;
using std::begin; using std::end;
std::copy( begin(v), end(v), begin(d) ); // this is the recommended way
return d;
}
That way, if you remove the assertion, this function would work even if v is a raw array.
It doesn't work with std::string, but if you're using a C string literal (char const *), C++20 introduces std::to_array for just this sort of thing:
std::array arr {"Hello, world!"};
https://en.cppreference.com/w/cpp/container/array/to_array