I am new to template meta programming. I want to strip args from variable argument in c++. I am making a function which will push_back() element to any type of container. Its very easy to do in C++ 17 but i want to provide support for C++ 11 . Please find the code below push_back() function implementation i am looking for. Please avoid va_start(), va_end() c style solution.
#include <iostream>
#include <vector>
template<class Container, class T, class... Args>
void push_back(Container& con, T tail, Args... args);
template<class T>
T get_tail(T data) {
return data;
}
template<class T, class ...Args>
T get_tail(T& tail, Args&... args) {
return tail;
}
template<class Container , class T,class... Args>
void push_back(Container& con, T tail,Args... args ) {
//C++ 17 ((con.push_back(args), ...);
con.push_back(tail);
std::cout << (tail) << std::endl;
T newTail = get_tail(args...);
push_back(con,newTail,args...);
}
template<typename T, typename... Args>
bool pair_comparer(T a, T b, Args... args) {
return a == b && pair_comparer(args...);
}
int main()
{
std::vector<int> v_int;
push_back(v_int,1,2,3,4 );
std::cout << "Hello World!\n";
for (auto iter = v_int.begin(); iter != v_int.begin(); iter++) {
std::cout << "=== " << *iter << " ===" << std::endl;
}
}
You've already stripped the first argument away when you did
void push_back(Container& con, T tail, Args... args ) {
tail is the first argument and args is the rest, so your recursive call at the end simply needs to say
pus_back(con, args...)
No need for any of this get_tail hackery. Then, simply have another overload of push_back that looks like this.
template <class Container>
void push_back(Container& con) {
// A whole lot of nothing happens here...
}
That handles the base case, and the function you already wrote (with the one minor modification) handles the recursive case.
Not sure to understand what do you exactly want but...
Are you sure you need recursion?
You can develop something similar the C++17 way unpacking the variadic args..., using the initialization of an unused C-style array, as follows
template <typename Container, typename ... Args>
void push_back (Container & con, Args ... args ) {
using unused = int[];
(void)unused { 0, ((void)con.push_back(args), std::cout << args << std::endl, 0)... };
}
Or simply as follows
template <typename Container, typename ... Args>
void push_back (Container & con, Args ... args ) {
using unused = int[];
(void)unused { 0, ((void)con.push_back(args), 0)... };
}
if the std::cout part is just for debugging purposes.
The problem in your code is that you call push_back inside of itself with the same number of arguments. This makes the recursion infinite. Instead you need to "strip" one argument each time. And certainly provide the recursion base. Like this:
template<class Container>
void push_back(Container& con) {
}
template<class Container , class T,class... Args>
void push_back(Container& con, T tail, Args... args ) {
con.push_back(tail);
std::cout << (tail) << std::endl;
push_back(con, args...);
}
int main()
{
std::vector<int> v_int;
push_back(v_int,1,2,3,4 );
std::cout << "Hello World!\n";
for (auto x : v_int)
std::cout << "=== " << x << " ===" << std::endl;
}
Related
I would like to create function calling another function and printing its arguments.
It should be compatible with many functions (returning the same result) with many combinations of variables of arguments.
I would like to have something like this:
int fun1(){}
int fun2(int i){}
int fun3(std::string s, int i){}
void execute_and_print(std::function f, ...)
{
///code
}
int main()
{
execute_and_print(&fun1);
execute_and_print(&fun2, 3);
execute_and_print(&fun3,"ff",4);
}
It could print:
executed function with arguments:
executed function with arguments: 3
executed function with arguments: ff, 4
Is it even possible in C++?
In C++17 it is very simple
template <typename F, typename... Args>
void execute_and_print(F f, Args... args)
{
(std::cout << ... << args);
f(args...);
}
Prior to that there is extra ceremony
template <typename F, typename... Args>
void execute_and_print(F f, Args... args)
{
int dummy[] = { (static_cast<void>(std::cout << args), 0)... };
f(args...);
}
It is not foolproof, but any possible errors will be caught at compile time (ie. the code will not compile). It should work file, as long as the provided parameters match those of the called function, and a matching << operator exists for each parameter.
template<class Fn, class...Args>
void execute_and_print(Fn fn, Args...args) {
int f[sizeof...(Args)] = { (std::cout << args << ", ", 0)... };
fn(args...);
}
Refer to https://en.cppreference.com/w/cpp/language/parameter_pack. The sizeof... command is actually the number of elements, not their combined size.
You can use templates to get it done,
template <class... Args>
void RunThrough(Args&& ... args)
{
([&](auto& input)
{
std::cout << input << ", ";
} (args), ...);
}
template<class Func, class... Args>
decltype(auto) execute_and_print(Func f, Args&&... args)
{
f(args...);
std::cout << "executed function with arguments: ";
RunThrough(args...);
std::cout << std::endl;
}
You can use lambdas, std::function objects and function pointers in this.
Reference: https://stackoverflow.com/a/60136761/11228029
This question already has answers here:
How to make a variadic macro for std::cout?
(4 answers)
Closed 3 years ago.
I want to create a C++ Template for a function, that allows per default intinity arguments of any datatypes. I found some examples where they try to Code the printf function but it doesn't work (they included stdarg.h, i want something like that:)
//util.cpp
#include <iostream>
template<typename ...Args>
void debugPrint(Args... args)
{
// pseudo: foreach args as a:
std::cout << a;
// pseudo: endforeach
std::cout << std::endl;
}
//util.hpp
template<typename ...Args> //?
void debugPrint(Args...);
//app.cpp
#include "util.hpp"
int main()
{
debugPrint("Hallo", " ", "Welt", 1, 2, "\t", 2.3);
return 0;
}
Want the consoleoutput:
Hallo Welt12 [TAB] 2.3
Then there were an examplte with stdarg.h
#include <stdarg.h>
void tprintf(const char* format) // base function
{
std::cout << format;
}
template<typename T, typename... Targs>
void tprintf(const char* format, T value, Targs... Fargs) // recursive function
{
for (; *format != '\0'; format++) {
if (*format == '%') {
std::cout << value;
tprintf(format + 1, Fargs...); // recursive call
return;
}
std::cout << *format;
}
}
So how? :(
Thanks for any answere <3
As with any recursive solution, you need a base case to terminate the recursion. In this situation the base case is when there are no arguments left to print, in which case you do nothing:
void debugPrint() { }
Then the recursive template function, which processes a single "first" argument and then recurses on the remaining variadic arguments:
template <typename FirstArg, typename ...Args>
void debugPrint(FirstArg arg, Args... args)
{
std::cout << arg;
debugPrint(args...);
}
Tying it all together:
#include <iostream>
void debugPrint() { }
template <typename FirstArg, typename ...Args>
void debugPrint(FirstArg arg, Args... args)
{
std::cout << arg;
debugPrint(args...);
}
int main()
{
debugPrint("Hallo", " ", "Welt", 1, 2, "\t", 2.3);
}
Outputs:
Hallo Welt12 2.3
You can use fold expressions to do that (C++17):
template<typename... Args>
void debugPrint(Args const&... args) {
(std::cout << ... << args);
}
It will expand args with a << between expanded expressions. There is no need for recursion.
Here's a live example.
I have the following pseudo code:
template <typename... Ts>
void f(int index) {
std::vector<std::function<void(void)>> funcs;
funcs.push_back([](){ std::cout << typeid(type_1).name() << std::endl; });
funcs.push_back([](){ std::cout << typeid(type_2).name() << std::endl; });
funcs.push_back([](){ std::cout << typeid(type_3).name() << std::endl; });
funcs.push_back([](){ std::cout << typeid(type_4).name() << std::endl; });
funcs[index]();
}
Imagine that the Ts... parameter pack holds type_1, type_2, type_3 and type_4.
how can I expand the parameter pack in order to achieve something like this? I mean - how can I get 4 push_back() calls if there are 4 parameters in the template pack, and also have the different types in the different lambdas? I don't know the syntax..
And can I actually get some sort of an array of such functions at compile time, so there are no push_backs at runtime?
C++17 solution is ok, but C++14 is best.
For C++17, something like this, I suppose
(funcs.push_back([](){ std::cout << typeid(Ts).name() << std::endl; }), ...);
or, better (IMHO), using emplace_back()
(funcs.emplace_back([](){ std::cout << typeid(Ts).name() << std::endl; }), ...);
But remeber that is
std::vector<std::function<void(void)>>
not
std::vector<std::function<void>>
In C++14 (and C++11) you can obtain something similar with the trick of intialization of the unused array; the function can be written as
template <typename ... Ts>
void f (int index)
{
using unused = int[];
std::vector<std::function<void(void)>> funcs;
(void)unused { 0, (funcs.emplace_back([]()
{ std::cout << typeid(Ts).name() << std::endl; }), 0)... };
funcs[index]();
}
Update.
From re-reading the question I think you just want to call the function once for the I'th type.
I which case it's trivial at compile time:
#include <array>
#include <type_traits>
#include <iostream>
#include <string>
template <class T>
void show_type()
{
std::cout << typeid(T).name() << std::endl;
}
template <typename... Ts>
void f(int index) {
using function_type = void(*)();
constexpr auto size = sizeof...(Ts);
constexpr std::array<function_type, size> funcs =
{
&show_type<Ts>...
};
funcs[index]();
}
int main()
{
for(int i = 0 ; i < 3 ; ++i)
f<int, double, std::string>(i);
}
example output:
i
d
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Something along these lines, perhaps:
template <typename... Ts>
void f(int index) {
int i = 0;
auto _ = {
(index == i++ ? ((std::cout << typeid(Ts).name() << std::endl) , 0) : 0) ...
};
}
Demo
If all you want to do is do something for the nth type in a template parameter pack, where n is a runtime variable, then the vector + function approach isn't really great. Better to add an index sequence in there and fold:
template <typename T> struct tag_t { using type = T; };
template <typename T> constexpr inline tag_t<T> tag{};
template <class F, size_t... Is, typename... Tags>
void match(F f, size_t i, std::index_sequence<Is...>, Tags... tags) {
auto inner = [&](auto tag) { f(tag); return true; };
bool matched = ((i == Is && inner(tags)) || ...);
if (!matched) {
// failure case?
}
}
template <typename... Ts, class F>
void match(F f, size_t i) {
return match(f, i, std::index_sequence_for<Ts...>(), tag<Ts>... );
}
template <typename... Ts>
void foo(int index) {
match<Ts...>([](auto tag){
std::cout << typeid(typename decltype(tag)::type).name() << std::endl;
}, index);
}
This construction allows you to add a failure case, where you might call the passed-in function with some special type:
struct failure { };
template <class F, size_t... Is, typename... Tags>
void match(F f, size_t i, std::index_sequence<Is...>, Tags... tags) {
auto inner = [&](auto tag) { f(tag); return true; };
bool matched = ((i == Is && inner(tags)) || ...);
if (!matched) {
f(failure{});
}
}
template <typename... Ts>
void foo(int index) {
match<Ts...>(overload(
[](auto tag){
std::cout << typeid(typename decltype(tag)::type).name() << std::endl;
},
[](failure ) { /* ... */ }
), index);
}
I want to be able to combine multiple different arguments into a single string using ostringstream. That way I can log the resulting single string without any random issues.
I got this far:
template <typename T>
void MagicLog(T t)
{
std::cout << t << std::endl;
}
template<typename T, typename... Args>
void MagicLog(T t, Args... args) // recursive variadic function
{
std::cout << t << std::endl;
MagicLog(args...);
}
template<typename T, typename... Args>
void LogAll(int logType, T t, Args... args)
{
std::ostringstream oss;
MagicLog(t);
MagicLog(args...);
//Log(logType, oss.str());
}
So I need to replace std::cout with the oss that I made in the LogAll function, I tried passing it as an argument to the other functions but it was complaining about a "deleted function"...
So: How can I get a recursive variadic function to accept another parameter, the ostringstream?
I don't really understand your problem. Just like what you did with your LogAll function, passing an ostream& as first parameter works like a charm:
#include <iostream>
#include <sstream>
template <typename T>
void MagicLog(std::ostream& o, T t)
{
o << t << std::endl;
}
template<typename T, typename... Args>
void MagicLog(std::ostream& o, T t, Args... args) // recursive variadic function
{
MagicLog(o, t);
MagicLog(o, args...);
}
template<typename... Args>
void LogAll(int logType, Args... args)
{
std::ostringstream oss;
MagicLog(oss, args...);
std::cout << oss.str();
}
int main()
{
LogAll(5, "HELLO", "WORLD", 42);
}
It was also possible to eliminate the duplicate code from your MagicLog function.
I'd like to use parameters pack, but find the problem.
Some code:
template <typename Function, typename... Args>
auto f(Function func, Args... args) -> decltype(func(args...))
{
auto f11 = std::bind(func, args...);
f11();
}
void print(const char* string)
{
std::cout << string << std::endl;
}
All of this works well:
f([] (const char* additional, const char* more) {
std::cout << "hello ( " << additional << ", " << more << " )" << std::endl;
}, "additional text", "and one more");
auto printFunction = std::bind(&print, std::placeholders::_1);
printFunction("hello from print bind");
f(print, "hello from print directly");
but if i would like to give std::function to parameters pack:
f([] (std::function<void(const char*)> printParamFunc) {
printParamFunc("hello from print from std::function");
}, printFunction);
application no more compiles.
So, what the problem to use function as parameter in pack?
Thanks.
UPDATE:
if change code of f to:
template <typename Function, typename... Args>
auto f(Function func, Args... args) -> decltype(func(args...))
{
func(args...);
}
it works well, but i wouldn't like to execute this function here, i wanna create function and pass it like param.
UPDATE2:
Code execution example: http://ideone.com/gDjnPq
UPDATE3:
Clear code with compilation error: http://ideone.com/50z7IN
I understand the situation a bit better now.
Problem can be retroduced by this code:
void print(const char* string)
{
std::cout << string << std::endl;
}
int main(int argc, char ** argv)
{
auto lambda = [] (std::function< void ( const char * ) > printParamFunc) {
printParamFunc("hello from lambda!");
};
std::bind(lambda, std::bind(print, std::placeholders::_1))();
}
Nested std::bind trying to evaluate and fails with conversion _1 to const char *. It is specific of std::bind.
We need analogue of boost::bind::protect -- functor storing other functor -- and it is solve problem:
template <class F>
struct lazy_evaluate {
typedef typename F::result_type T;
explicit lazy_evaluate(F f) : f_(f) {}
template <class... Args>
T operator()(Args&&... args)
{
f_(std::forward<Args>(args)...);
}
private:
F f_;
};
template <class F>
lazy_evaluate<F> lazy(F f)
{
return lazy_evaluate<F>(f);
}
nested std::bind now looks like:
std::bind(lambda, lazy(std::bind(print, std::placeholders::_1)))();
and works well.