There is a generator which generates a tuple of 16 integers with each iteration. I want to add these tuples into a vector. While creating the vector I have to write std::vector<std::tuple<int, int, .... 16 times>>. Is there another way to create a vector of these tuples.
Code to test for the case of tuples containing 5 integers:
#include "cppitertools/itertools.hpp"
#include <iostream>
#include <tuple>
#include <vector>
int main()
{
std::vector<int> v1{0, 1};
std::vector<std::tuple<int, int, int, int, int>> states;
for (auto&& i : iter::product<5>(v1))
{
states.push_back(i);
}
auto size = states.size();
std::cout << size << std::endl;
}
I'm using cppiterator
template<size_t Remaining, typename Type,typename ... Args>
struct make_tuple_n_impl{
using type=typename make_tuple_n_impl<Remaining-1,Type,Type,Args...>::type;
};
template<typename T,typename ... Args>
struct make_tuple_n_impl<0,T,Args...>{
using type=std::tuple<Args...>;
};
template<size_t Count,typename Type>
using tuple_of=typename make_tuple_n_impl<Count,Type>::type;
Then tuple_of<5,int> is std::tuple<int,int,int,int,int>.
You can just fiddle the tuple type that iter::product creates
#include "cppitertools/itertools.hpp"
#include <iostream>
#include <tuple>
#include <vector>
template <typename>
struct remove_tuple_reference;
template <typename... Ts>
struct remove_tuple_reference<std::tuple<Ts...>> {
using type = std::tuple<std::remove_reference_t<Ts>...>;
};
template <typename T>
using remove_tuple_reference_t = typename remove_tuple_reference<T>::type;
int main()
{
std::vector<int> v1{0, 1};
using tup = remove_tuple_reference_t<decltype(iter::product<5>(v1).begin())::value_type>;
std::vector<tup> states;
for (auto&& i : iter::product<5>(v1))
{
states.push_back(i);
}
auto size = states.size();
std::cout << size << std::endl;
}
Related
How would I make a std::vector that contains a default-constructed instance of all the types contained in a std::variant?
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
std::vector<TaskVariant> variants;
// I'd like to do this in a loop
variants.push_back(TypeA());
variants.push_back(TypeB());
variants.push_back(TypeC());
1.Solution: You can convert variant to tuple and then use C++17 std::apply:
#include <variant>
#include <iostream>
#include <string>
#include <vector>
#include <tuple>
using namespace std;
template <typename... Types>
struct ToTuple;
template <typename... Types>
struct ToTuple<variant<Types...>>
{
using type = tuple<Types...>;
};
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
int main()
{
vector<TaskVariant> vec;
apply([&vec](auto&&... args) {(vec.push_back(args), ...); }, ToTuple<TaskVariant>::type{});
}
EDIT:
2.Solution: Using make_index_sequence, variant_alternative_t and variant_size_v (all C++17) (thanks to #s d by pointing out to variant_alternative_t, but I have modified example by using make_index_sequence instead of recursion):
#include <variant>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
template <size_t... Idx>
void fill_vec(vector<TaskVariant>& vec, index_sequence<Idx...> idx)
{
(vec.push_back(variant_alternative_t<Idx, TaskVariant>{}), ...);
}
int main()
{
vector<TaskVariant> vec;
fill_vec(vec, make_index_sequence<variant_size_v<TaskVariant>>{});
}
Yet another solution
#include <iostream>
#include <variant>
#include <vector>
struct TypeA {
int a;
TypeA() : a{0} {std::cout<<"A"<<std::endl;};
};
struct TypeB {
int b;
TypeB() : b{0} {std::cout<<"B"<<std::endl;};
};
struct TypeC {
int c;
TypeC() : c{0} {std::cout<<"C"<<std::endl;};
};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
template<class var, std::size_t I = 0>
void autofill(std::vector<var>& vec){
if constexpr(I < std::variant_size_v<var>){
vec.push_back(std::variant_alternative_t<I, var>{});
autofill<var, I + 1>(vec);
}
}
int main() {
std::vector<TaskVariant> variants;
autofill(variants);
}
Edit: completely forgot about this feature in C++17.
template<class... VA> //VA for variant alternatives
void autofill(std::vector<std::variant<VA...> >& vec) {
(..., vec.emplace_back(VA{}));
}
https://en.cppreference.com/w/cpp/language/fold
edit 2: seems like #max beat me to that about 4 hours ago ^^
What about using template folding (comma operator) over types?
#include <variant>
#include <vector>
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
template <typename ... Ts>
void addTypes (std::vector<std::variant<Ts...>> & vec)
{ (vec.push_back(Ts{}), ...); }
int main()
{
std::vector<TaskVariant> vec;
addTypes(vec);
}
Here sample solution using variadic templates.
#include <vector>
#include <variant>
#include <iostream>
#include <typeinfo>
struct TypeA {};
struct TypeB {};
struct TypeC {};
using TaskVariant = std::variant<TypeA, TypeB, TypeC>;
template <class T>
void addValue(std::vector<TaskVariant> & v)
{
v.push_back(T());
std::cout << "adding " << typeid(T).name() << " default ctor\n";
}
template <class T, class V, class... Args>
void addValue(std::vector<TaskVariant> & v)
{
addValue<T>(v);
addValue<V, Args...>(v);
}
template <class... Args>
void addValues(std::vector<std::variant<Args...>> & v)
{
addValue<Args...>(v);
}
int main()
{
std::vector<TaskVariant> variants;
addValues(variants);
}
Output is:
adding 5TypeA default ctor
adding 5TypeB default ctor
adding 5TypeC default ctor
This is the extraction of a follow-up question to this answer.
Given the following "loop" technique
#pragma once
// loop.hpp
#include <type_traits>
#include <utility>
template<std::size_t... indices, class LoopBody>
void loop_impl(std::index_sequence<indices...>, LoopBody&& loop_body) {
(// C++17's fold expression
loop_body(std::integral_constant<std::size_t, indices>{}),
...
);
}
template<std::size_t N, class LoopBody>
void loop(std::integral_constant<std::size_t, N>, LoopBody&& loop_body) {
loop_impl(std::make_index_sequence<N>{}, std::forward<LoopBody>(loop_body));
}
it is possible to iterate over a type list like this:
#include <iostream>
#include <string_view>
#include <tuple>
#include "loop.hpp"
template<class T>
std::string_view inspect() {
return __PRETTY_FUNCTION__;
}
using Types = std::tuple<int, int, char, bool, double>;
int main() {
loop(std::tuple_size<Types>{}, [&] (auto i) {
using T = std::tuple_element_t<i, Types>;
std::cout << i << ": " << inspect<T>() << "\n";
});
}
... but how to iterate over a list of templates?
Using Boost.Mp11, the first version is:
static constexpr auto size = std::tuple_size_v<Types>;
mp_for_each<mp_iota_c<size>>([&] (auto i) {
/* ... */
});
Doing this over templates works basically the same way:
using list = mp_list<mp_quote<std::tuple>, mp_quote<std::pair>>;
mp_for_each<list>([&](auto f){
// v is a tuple<int, char> the first time around and a pair<int, char>
// the second time around
mp_invoke_q<decltype(f), int, char> v;
});
Of course you can do whatever you want with f in the body, I just invoked it as an example of mp_quote and how well integrated it is with the rest of Mp11.
You may wrap templates of the form template<class...> class into a tag type like the following:
#pragma once
// template_tag.hpp
#include <tuple>
#include <type_traits>
template<
template<class...>
class Tmpl_
>
struct TemplateTag {
template<class... Ts>
using insert = Tmpl_<Ts...>;
template<
template<template<class... > class>
class TmplTmpl
>
using rewrap_into = TmplTmpl<Tmpl_>;
};
// convenience helper
template<class TmplTag, class... Ts>
using InsertTemplateArgs = typename TmplTag::template insert<Ts...>;
static_assert(
std::is_same<
InsertTemplateArgs< TemplateTag<std::tuple>, int, bool >,
std::tuple<int, bool>
>{}
);
// convenience helper
template<class TmplTag, template<template<class...> class> class TmplTmpl>
using RewrapTemplateInto = typename TmplTag::template rewrap_into<TmplTmpl>;
template<template<class...> class Tmpl>
struct OtherTemplateTag {};
static_assert(
std::is_same<
RewrapTemplateInto< TemplateTag<std::tuple>, OtherTemplateTag >,
OtherTemplateTag<std::tuple>
>{}
);
Once your templates are wrapped into a tag type, you can iterate over the types as before:
#include <iostream>
#include <string_view>
#include <tuple>
#include <utility>
#include <variant>
#include "loop.hpp"
#include "template_tag.hpp"
template<class T>
std::string_view inspect() {
return __PRETTY_FUNCTION__;
}
using Templates = std::tuple<
TemplateTag<std::tuple>,
TemplateTag<std::tuple>,
TemplateTag<std::pair>,
TemplateTag<std::variant>
>;
template<
template<class...>
class Tmpl
>
struct AnotherTemplateTag {};
int main() {
loop(std::tuple_size<Templates>{}, [&] (auto i) {
using TmplTag = std::tuple_element_t<i, Templates>;
std::cout << i << ": " << inspect<TmplTag>() << "\n";
using AnotherTmplTag = RewrapTemplateInto<TmplTag, AnotherTemplateTag>;
std::cout << " " << inspect<AnotherTmplTag>() << "\n";
using TmplWithArgs = InsertTemplateArgs<TmplTag, int, long>;
std::cout << " " << inspect<TmplWithArgs>() << "\n";
});
}
I have a function with two template arguments, one for a vector data type (int, float, double, etc.) and one for an integer type (int, int16_t, uint32_t, etc.):
template <typename T, typename I>
void
add(std::vector<T> array, std::vector<I> idx) {
// ...
}
For tests, I would now like to loop over every possible combination of data/integer types, e.g.,
// pseudo code
for I in [int, int16_t, int32_t, ...] {
for T in [float, double, int, int16_t, ...] {
// create arguments a, b
add<T, I>(a, b);
}
}
Is it possible to loop over types at all? How?
There may be simpler ways to do this, but I would use the boost hana library, as follows:
#include <boost/hana/for_each.hpp>
#include <boost/hana/tuple.hpp>
#include <vector>
#include <iostream>
#include <boost/type_index.hpp>
namespace hana = boost::hana;
// for example's sake, just print the type
template <typename T, typename I>
void add(std::vector<T> array, std::vector<I> idx) {
using namespace boost::typeindex;
std::cout << type_id<T>().pretty_name() << " - " << type_id<I>().pretty_name() << std::endl;
}
int main() {
auto types1 = hana::tuple_t<int, int16_t, int32_t>;
auto types2 = hana::tuple_t<float, double, int, int16_t>;
hana::for_each(types1, [types2](auto t1) {
hana::for_each(types2, [t1](auto t2) {
using t1_type = typename decltype(t1)::type;
using t2_type = typename decltype(t2)::type;
add<t1_type, t2_type>({}, {});
});
});
}
If you have boost at hand then boost::hana is definitely the way to go. However, it's not very hard to reimplement that feature by hand if you have to:
#include <iostream>
template<typename... T>
struct iterator {
template<typename CB_T>
static void iterate(CB_T const& ) {}
};
template<typename first, typename... rest>
struct iterator<first, rest...> {
template<typename CB_T>
static void iterate(CB_T const& cb) {
cb(first());
iterator<rest...>::iterate(cb);
}
};
int main() {
iterator<int, float>::iterate([](auto const & v_1){
using v_1_t = decltype(v_1);
iterator<char, double>::iterate([&](auto const & v_2){
using v_2_t = decltype(v_2);
std::cout << typeid(v_1_t).name() << " vs " << typeid(v_2_t).name() << "\n";
});
});
return 0;
}
I am trying to write a handler class that when given a tuple, it can dynamically handle a specific field from the given tuple.
The problem is, I don't know how to create an instance of that class because the class is templated, and the template I need for the instantiation is inside the tuple.
(It is important to have the handler in a separate class due to design requests which are irrelevant to the question)
Notice the ??? in the ILevelHandler instance, I am required to supply the template but I'm not sure how to do it.
#include <tuple>
#include <string>
#include <iostream>
#include <boost/variant.hpp>
template <typename... T>
class ILevelHandler
{
public:
virtual void HandleEnterLevel(const boost::variant<T...>& _value)
{
std::cout << " value: " << _value << std::endl;
}
};
int main()
{
std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};
ILevelHandler<???> lvl(tpl);
for (size_t i = 0; i < 4; ++ i)
{
lvl.HandleEnterLevel(i, dynamic_get(i, tpl));
}
return 0;
}
Important to mention: solving the problem with a function that is not wrapped inside a class is easy, although, I need to supply an abstract class, so that the user will have to implement the function on his own.
As a possible solution, you can use a support fake function as it follows:
#include <tuple>
#include <string>
template <typename... T>
class ILevelHandler {
public:
ILevelHandler(const std::tuple<T...> &) {}
};
template<typename... T>
auto f(const std::tuple<T...> &) -> ILevelHandler<T...>;
int main() {
std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};
decltype(f(tpl)) lvl(tpl);
return 0;
}
Note that you don't need to define the function f, a simple declaration like the one in the example above is enough.
You can use also a couple of using declarations to clean up a bit your statements:
// ...
template<typename T>
using MyILevelHandler = decltype(f(std::declval<T>()));
// ...
int main() {
using MyTuple = std::tuple<int, float, std::string, int>;
MyTuple tpl {4, 6.6, "hello", 7};
MyILevelHandler<MyTuple> lvl(tpl);
return 0;
}
assuming you have already written dynamic_get (say if you need help with that) then a simple conversion class should do it:
#include <tuple>
#include <string>
#include <iostream>
#include <boost/variant.hpp>
template <typename... T>
class ILevelHandler
{
public:
void HandleEnterLevel(const boost::variant<T...>& _value)
{
std::cout << " value: " << _value << std::endl;
}
};
template<class Thing>
struct to_variant;
template<class...T>
struct to_variant<std::tuple<T...>>
{
using type = boost::variant<T...>;
};
template<class T> using to_variant_t = typename to_variant<T>::type;
int main()
{
std::tuple<int, float, std::string, int> tpl {4, 6.6, "hello", 7};
using tuple_type = decltype(tpl);
using variant_type = to_variant_t<tuple_type>;
ILevelHandler< variant_type > lvl;
for (size_t i = 0; i < 4; ++ i)
{
lvl.HandleEnterLevel(i, dynamic_get(i, tpl));
}
return 0;
}
On the following code I defined an unsigned int called my_type, which I use to print the maximum value of the type itself:
#include <iostream>
#include <limits>
#include <cmath>
...
using namespace std;
int main() {
typedef unsigned int my_type;
const my_type max_int = numeric_limits<my_type>::max():
cout << max_int << endl;
return 0;
}
How can I do the same for multiple types without having to duplicate this code?
I tried creating a string array that would store types unsigned int and long (as an example), but that didn't work:
string current_type[2] = {"unsigned int", "long"};
loop{
typedef current_type[0..1] my_type;
const my_type max_int = numeric_limits<my_type>::max();
}
I have also tried using templates, but couldn't figure it out how to do it.
Is this even possible?
#include <iostream>
#include <limits>
using namespace std;
template <typename T>
void printMax()
{
cout << numeric_limits<T>::max() << endl;
}
int main()
{
printMax<unsigned int>();
printMax<double>();
return 0;
}
And:
$ g++ test.cpp && ./a.out
4294967295
1.79769e+308
C++ has no reflection so you can't convert c++ string to type name. But you can use variadic templates for your task.
#include <iostream>
#include <limits>
#include <cmath>
using namespace std;
template <typename ... Args>
struct TL;
template <typename T>
struct TL<T>
{
static void print()
{
const T max_int = numeric_limits<T>::max();
cout << max_int << endl;
}
};
template <typename T, typename ... Args>
struct TL<T, Args...>
{
static void print()
{
TL<T>::print();
TL<Args...>::print();
}
};
int main(int , char** )
{
TL<int, unsigned int, short int>::print();
return 0;
}
UPDATE
More complicated example.
You can declare variadic template for holding type lists:
template <typename ... Args>
struct TypeList;
template <typename T>
struct TypeList<T>
{
typedef T type;
};
template <typename T, typename ... Args>
struct TypeList<T, Args...>
{
typedef T type;
// typedef TypeList<Args...> rest;
};
and template to perform operation, depended of type for each element in type list:
template <typename L, template <typename T> class Op>
struct ForEach;
template <typename T, template <typename T> class Op>
struct ForEach<TypeList<T>, Op>
{
void operator()()
{
Op<T>()();
}
};
template <typename T, template <typename T> class Op, typename ... Args>
struct ForEach<TypeList<T, Args...>, Op>
{
void operator()()
{
Op<T>()();
ForEach<TypeList<Args...> , Op>()();
}
};
Now, you can declare some functions like templated structs with operator()
#include <iostream>
#include <limits>
#include <cmath>
using namespace std;
template <typename T>
struct PrintNumericTypeMaxLimit
{
void operator()()
{
const T max_int = numeric_limits<T>::max();
cout << max_int << endl;
}
};
template <typename T>
struct PrintNumericTypeMinLimit
{
void operator()()
{
const T min = numeric_limits<T>::min();
cout << min << endl;
}
};
And use it with your type list:
int main(int , char** )
{
typedef TypeList<int, unsigned int, long int, short int, unsigned short int, double> myList;
ForEach<myList, PrintNumericTypeMaxLimit>()();
ForEach<myList, PrintNumericTypeMinLimit>()();
return 0;
}
You could use boost::variant to inform the types you want, boost::mpl::foreach to loop over them
and a functor to print the numeric limits in a pre-c++11 manner or with a c++11 lambda
#include <iostream>
#include <limits>
#include <boost/variant.hpp>
#include <boost/mpl/for_each.hpp>
struct printMaxNumLimits
{
template<class Type>
void operator()(Type t) {
std::cout << std::numeric_limits<Type>::max() << std::endl;
}
};
int main()
{
using variant_types = boost::variant<int, double, unsigned int>;
// pre c++11
boost::mpl::for_each<variant_types::types>(printMaxNumLimits());
// c++11
boost::mpl::for_each<variant_types::types>([](auto t){
std::cout << std::numeric_limits<decltype(t)>::max() << std::endl;
});
}
Live example