loop parameter pack lambda - c++

I have a small bit of code.
I want to know if i could cut out my ProcessArg function
I would like to loop the parameter pack from inside my call function.
Im i best to use a lambda function in initializer_list or something else, if so how do i do it.
Thanks
template <class R, class Arg>
R ProcessArg(Arg&& arg) {
std::cout << typeid(arg).name() << (std::is_reference<Arg>::value ? "&" : "") << std::endl;
//std::cout << std::boolalpha << std::is_reference<Arg>::value << std::endl; // not always true
return R();
}
template <typename R, typename... Args>
R CallFunction(Args&&... args) {
std::size_t size = sizeof...(Args);
std::initializer_list<R>{ProcessArg<R>(std::forward<Args>(args)) ...};
return R();
}
template<typename Fn> class FunctionBase;
template<typename R, typename... Args>
class FunctionBase <R(*)(Args...)> {
public:
FunctionBase() {}
R operator()(Args&&... args) { // Args&& is a universal reference
return CallFunction<R>(std::forward<Args>(args)...);
}
};
int foo(int a, int& b) {
std::cout << std::boolalpha << std::is_reference<decltype(a)>::value << std::endl; // falae
std::cout << std::boolalpha << std::is_reference<decltype(b)>::value << std::endl; // true
return a + b;
}
int main() {
int in = 10;
foo(1, in);
FunctionBase<decltype(&foo)> func;
func(1, in);
}

With c++17 fold-expressions, you can replace:
std::initializer_list<R>{ProcessArg<R>(std::forward<Args>(args)) ...};
with:
((std::cout << typeid(args).name()
<< (std::is_reference<Args>::value ? "&" : "")
<< std::endl
), ...);
Or with a lambda expression to improve readability:
auto process = [](auto&& arg) {
std::cout << typeid(arg).name()
<< (std::is_lvalue_reference<decltype(arg)>::value ? "&" : "")
<< std::endl;
};
(process(std::forward<Args>(args)), ...);
In c++20:
auto process = [] <typename Arg> (Arg&& arg) {
std::cout << typeid(arg).name()
<< (std::is_reference<Arg>::value ? "&" : "")
<< std::endl;
};
(process(std::forward<Args>(args)), ...);

Related

Variadic template and std::array unexpected behaviour

I can compile but I have problems in running the following code (I minimized it):
#include <iostream>
#include <array>
template<int N>
class Selector {
public:
template <typename... Args>
Selector(int x, Args... args) noexcept {
integers[sizeof...(Args)] = x;
std::cout << "integers[" << sizeof...(Args) << "]=" << integers[sizeof...(Args)] << std::endl; // OK
Selector(args...);
}
Selector(int x) noexcept {
integers[0] = x;
std::cout << "integers[0]=" << integers[0] << std::endl; // OK
}
void print_num(int i) const {
std::cout << "integers[" << i << "]=" << integers[i] << std::endl;
}
private:
std::array<int, N> integers;
};
int main() {
Selector<3> x(5, 10, 15);
x.print_num(2); // OK
x.print_num(1); // KO
x.print_num(0); // KO
}
The output is:
integers[2]=5
integers[1]=10
integers[0]=15
integers[2]=5
integers[1]=1016039760
integers[0]=22034
Clearly the first two cells of the array have garbage numbers after the object initialization. I suspect that I'm corrupting the stack in some way, but I cannot figure out why/where...
The statement Selector(args...); in the constructor, just constructs a temporary object which gets destroyed immediately; it does nothing relevent to the current object.
I suppose you want delegating constructor (since C++11):
template <typename... Args>
Selector(int x, Args... args) noexcept : Selector(args...) {
// ^^^^^^^^^^^^^^^^^^^
integers[sizeof...(Args)] = x;
std::cout << "integers[" << sizeof...(Args) << "]=" << integers[sizeof...(Args)] << std::endl; // OK
}
LIVE

How to implement a strange for loop

Is it possible to create a loop pattern that will allow me to change operators?
Like this
template <typename T1, typename T2, typename T3, typename T4>
auto test(T1 a, T2 b, T3 c, T4 x)
{
cout << a << endl;
cout << b << endl;
for (; a c b; a x)
{
cout << a << " |a " << this_thread::get_id() << "\n" << endl;
}
}
// main
// test(2.242, <, 20, ++);
You simply can pass any kind of function to your template. Here I use lambdas for that purpose.
As the lambdas itself are templated, you can use any kind of types in your loop.
In the loop itself we simply call the given functions. Thats easy? ;)
template <typename VAR_TYPE1, typename VAR_TYPE2, typename PREDICATE_TYPE, typename INCREMENT_FUNC_TYPE>
auto test(VAR_TYPE1 a, VAR_TYPE2 b, PREDICATE_TYPE predicate, INCREMENT_FUNC_TYPE incrementFunc )
{
std::cout << a << std::endl;
std::cout << b << std::endl;
// we simply call the given functions for the predicate/condition and the increment
for (; predicate(a,b); incrementFunc(a) )
{
std::cout << a << std::endl;
}
}
int main()
{
// use with lambdas
test( 1,9, []( auto a, auto b){ return a < b; }, []( auto& a ) { return a++; });
std::cout << std::endl;
// use with stl defined predicates
test( 1,9, std::less{} , []( auto& a ) { return a++; });
std::cout << std::endl;
test( 10.1, 5.5, std::greater{} , []( auto& a ) { return a-=0.2; });
}

Variadic template function: argument number for each argument

I'm playing around with variadic function templates in C++11 and have got the basic idea with code something like:
void helper()
{
std::cout << "No args" << std::endl;
}
template< typename T >
void helper( T&& arg )
{
size_t n = 0;
std::cout << "arg " << n << " = " << arg << std::endl;
helper();
}
template< typename T, typename... Arguments >
void helper( T&& arg, Arguments&& ... args )
{
size_t n = sizeof...( args );
std::cout << "arg " << n << " = " << arg << std::endl;
helper( args... );
}
However, what I want is for the argument number (the variable n in the code) to count up rather than down. How can I do this elegantly? I could write a wrapper function that creates a 'hidden' argument count but I feel there should be a neater way?
Thanks!
Do you mean something like this? I think I understand what you're looking for, but if not I'll not hesitate to drop this answer:
#include <iostream>
#include <utility>
void helper()
{
std::cout << "no args" << std::endl;
}
template<size_t N, typename T>
void helper(T&& arg)
{
std::cout << "arg " << N << " = " << arg << std::endl;
}
template<size_t N, typename T, typename... Args>
void helper(T&& arg, Args&&... args)
{
helper<N>(std::forward<T>(arg));
helper<N+1, Args...>(std::forward<Args>(args)...);
}
template<typename T, typename... Args>
void helper(T&& arg, Args&& ... args)
{
helper<0>(std::forward<T>(arg), std::forward<Args>(args)... );
}
int main()
{
helper();
std::cout << '\n';
helper("single");
std::cout << '\n';
helper("one", 2U);
std::cout << '\n';
helper(1,"two", 3.0, 4L);
std::cout << '\n';
return 0;
}
Output
no args
arg 0 = single
arg 0 = one
arg 1 = 2
arg 0 = 1
arg 1 = two
arg 2 = 3
arg 3 = 4
See it live
You may do the following: live example
#if 1 // Not in C++11 // make_index_sequence
#include <cstdint>
template <std::size_t...> struct index_sequence {};
template <std::size_t N, std::size_t... Is>
struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct make_index_sequence<0u, Is...> : index_sequence<Is...> {};
#endif // make_index_sequence
namespace detail
{
template<std::size_t...Is, typename... Ts>
void helper(index_sequence<Is...>, Ts&&...args)
{
int dummy[] = {0, ((std::cout << "arg " << Is << " = " << args << std::endl), 0)...};
static_cast<void>(dummy);
}
}
void helper()
{
std::cout << "No args" << std::endl;
}
template<typename ... Ts>
void helper(Ts&&... args)
{
detail::helper(make_index_sequence<sizeof...(Ts)>(), std::forward<Ts>(args)...);
}

variadic template function casts array type to pointer

This code has a partial user specializations for pointers and arrays.
When the array specialization is explicitly called, the expected value is returned.
However, when a variadic template function is used, the array parameter is converted to a pointer, and the pointer specialization is called.
Is there a way to get the compiler (g++ 4.8.1 in this case) to not do that cast?
Or is there a different way to return the "total size" that doesn't use template specializations?
#include <iostream>
template <typename T, typename... Params>
struct TestTemplate
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return sizeof (T) + TestTemplate<Params...>::Sizeof();
}
};
template <typename T>
struct TestTemplate<T>
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return sizeof (T);
}
};
template <typename T, typename... Params>
struct TestTemplate<T*, Params...>
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return sizeof (T) + TestTemplate<Params...>::Sizeof();
}
};
template <typename T>
struct TestTemplate<T*>
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return sizeof (T);
}
};
template <typename T, size_t N, typename... Params>
struct TestTemplate<T[N], Params...>
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return N * sizeof (T) + TestTemplate<Params...>::Sizeof();
}
};
template <typename T, size_t N>
struct TestTemplate<T[N]>
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return N * sizeof (T);
}
};
template <typename... Params>
size_t GetSizeof (Params... params)
{
return TestTemplate<Params...>::Sizeof();
}
struct TestType
{
double x = 0., y = 0.;
char buf[64];
};
int main (int, char *[])
{
std::cout << TestTemplate<int[10]>::Sizeof() << std::endl; // prints 40. OK
std::cout << GetSizeof (2, 3, 4) << std::endl; // prints 12. OK
TestType tt;
std::cout << GetSizeof (&tt, 1) << std::endl; // prints 84. OK
int int_arr[10];
std::cout << GetSizeof (int_arr, 1) << std::endl; // prints 8, want 41
}
You may replace your GetSizeof by: (https://ideone.com/jqXT4s)
template <typename... Params>
size_t GetSizeof (const Params&... params)
{
return TestTemplate<Params...>::Sizeof();
}
Once you have done that, you may simply use:
template <typename T, typename... Params>
struct TestTemplate
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return sizeof (typename std::remove_pointer<T>::type) + TestTemplate<Params...>::Sizeof();
}
};
template <typename T>
struct TestTemplate<T>
{
static size_t Sizeof()
{
std::cout << __FILE__ << ':' << __LINE__ << std::endl;
return sizeof (typename std::remove_pointer<T>::type);
}
};
as sizeof(T[N]) == N * sizeof(T).

Output a tuple within an STL list

void output_list_contents(std::list<tuple<string, int, double,int>> &my_list)
{
for(std::list<tuple<string, int, double,int> >::iterator it =my_list.begin(); it!= my_list.end(); ++it)
{
}
}
I'm trying to output the information from all tuples stored within an STL list. I don't know the syntax and I have spent the past hour googling for an answer, but sadly I haven't come across anything. I'm struggling with the syntax and logic to get access to the tuples stored within.
Can anyone help me out here please?
Something like:
void output_list_contents(std::list<tuple<string, int, double,int>> &my_list)
{
for(const auto& e : my_list)
{
std::cout << std::get<0>(e) << " " << std::get<1>(e) << " "
<< std::get<2>(e) << " " << std::get<3>(e) << std::endl;
}
}
First overload operator<< for tuple<string, int, double,int>:
std::ostream& opertaor<<(std::ostream& out,
tuple<string,int,double,int> const & t)
{
return out << "{" << std::get<0>(t)
<< "," << std::get<1>(t)
<< "," << std::get<2>(t)
<< "," << std::get<3>(t) << "}";
}
then use it in the loop as:
for(std::list<tuple<string, int, double,int> >::iterator it =my_list.begin();
it!= my_list.end(); ++it)
{
std::cout << *it << std::endl;
}
Oh that is ugly. Better use range-based for loop and auto:
for(auto const & item : my_list)
std::cout << item << std::endl;
Hope that helps.
A generalized implementation of operator<< for std::tuple would be this:
namespace detail
{
template<int ... N>
struct seq
{
using type = seq<N...>;
template<int I>
struct push_back : seq<N..., I> {};
};
template<int N>
struct genseq : genseq<N-1>::type::template push_back<N-1> {};
template<>
struct genseq<0> : seq<> {};
template<typename ... Types, int ...N>
void print(std::ostream & out, std::tuple<Types...> const & t, seq<N...>)
{
const auto max = sizeof...(N);
auto sink = {
(out << "{", 0),
(out << (N?",":"") << std::get<N>(t) , 0)...,
(out << "}", 0)
};
}
}
template<typename ... Types>
std::ostream& operator<<(std::ostream & out, std::tuple<Types...> const & t)
{
detail::print(out, t, typename detail::genseq<sizeof...(Types)>::type());
return out;
}
This generalized operator<< should be able to print std::tuple with any number of template arguments, as long as all template arguments support operator<< in turn.
Test code:
int main()
{
std::cout << std::make_tuple(10, 20.0, std::string("Nawaz")) << std::endl;
std::cout << std::make_tuple(10, 20.0, std::string("Nawaz"), 9089) << std::endl;
}
Output:
{10,20,Nawaz}
{10,20,Nawaz,9089}
Online Demo :-)
void output_list_contents(std::list<std::tuple<std::string, int, double, int>>& my_list)
{
for (auto tup : my_list)
{
print_tuple(tup);
}
}
And this is how print_tuple looks:
template <typename... Ts, int... Is>
void print_tuple(std::tuple<Ts...>& tup, std::index_sequence<Is...>)
{
auto l = { ((std::cout << std::get<Is>(tup)), 0)... };
}
template <typename... Ts>
void print_tuple(std::tuple<Ts...>& tup)
{
print_tuple(tup, std::index_sequence_for<Ts...>{});
}