#include <cstdio>
#include <string>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/lexical_cast.hpp>
struct CLASS{
template<typename T, typename ... Args>
void enqueue(T const & t, Args const & ... args){
this->concatenate(t,args ...);
}
template<typename T, typename ... Args>
void concatenate(T t, Args ... args){
boost::function<void()> f
= boost::bind(&CLASS::push_,this,
boost::bind(&CLASS::stringer<T const &,
Args const & ...>,
this,boost::ref(t),boost::ref(args)...));
}
template<typename T, typename ... Args>
std::string stringer(T const & t, Args const & ... args){
return stringer(t) + stringer(args...);
}
template <typename T>
std::string stringer(T const & t){
return boost::lexical_cast<std::string>(t);
}
void push_(std::string const & s){
std::fprintf(stderr,"%s\n",s.c_str());
}
};
int main(){
CLASS c;
c.enqueue(42,"hello",35);
// below commented enqueue fails to compile
//c.enqueue("abc", 100," for ", 42000,"sadada ", 4.3, "zzzzz\n",42,42);
return 0;
}
In the main function above, the commented line fails to compile, although the uncommented enqueue does work. I have a feeling the problem is to do with the unwinding of the variadics by the stringer function and boost::bind failing to figure out overloads or something.
How do I solve this problem, so that enqueue works for any combination of inputs?
under c++11,we cannot bind a overload function.
but there is solution under C++14:
example:
struct ulong_ip_tag{};
struct string_ip_tag{};
struct resolved_ip_tag{};
struct invalid_ip_tag{};
template<typename _Type, typename _Handler>
void handler(_Handler, _Type)
{
std::cout << "other type" << std::endl;
}
template<typename _Handler>
void handler(_Handler, resolved_ip_tag)
{
std::cout << typeid(resolved_ip_tag).name() << std::endl;
}
template<typename _Handler>
void handler(_Handler, string_ip_tag)
{
std::cout << typeid(string_ip_tag).name() << std::endl;
}
template<typename _Handler>
void handler(_Handler, ulong_ip_tag)
{
std::cout << typeid(ulong_ip_tag).name() << std::endl;
}
void test(){}
int main()
{
//auto--- under c++14
auto b = [](auto arg1,auto arg2){handler(arg1,arg2)};
std::bind(b,test,ulong_ip_tag());
}
Related
I'm trying to implement a wrapper class for a function so that I can add methods to functions. I've created the class, but the operator() only works for some functions. What am I missing?
Code:
#include <iostream>
#include <functional>
template <typename R, typename... Args> class Function;
template <typename R, typename... Args>
class Function<R(Args...)> {
typedef R return_t;
typedef R func_t(Args...);
public:
std::function<func_t> value;
Function(func_t f){
this->value = f;
};
return_t operator()(Args... args){
(std::cout << ... << args) << "\n";
return this->value((..., args));
};
};
typedef int func(int, char);
int f(int, char);
int main(){
func f;
Function<func> t(f);
//std::cout << t.value(10, 'c') << std::endl;
std::cout << t(10, 'c');
}
// Test function
int f(int a, char c){
std::cout << c << std::endl;
return a;
}
I have a std::tuple, and I want to unwrap the contents using std::index_sequence in order to call a variadic function template
Consider the following example code:
#include <iostream>
#include <tuple>
template<typename... Ts>
void foo(const std::string& s, Ts... ts)
{
std::cout << "foo called with " << s << " and " << sizeof...(Ts) << " ts\n";
}
template<typename Tuple, std::size_t... Ixs>
void call_foo(const std::string& s, Tuple& t, std::index_sequence<Ixs...>)
{
foo(s, std::get<Ixs>(t)...);
}
template<typename... Ts>
struct Bar
{
Bar(Ts... ts) : t(ts...)
{ }
void do_it()
{
call_foo("hi", t, std::make_index_sequence<std::tuple_size<decltype(t)>::value>{});
}
std::tuple<Ts...> t;
};
template<typename... Ts> Bar<Ts...> make_bar(Ts... ts) { return Bar<Ts...>(ts...); }
int main ()
{
auto bar = make_bar(1, 'a', 2.3);
bar.do_it();
}
Note that I have to call through call_foo with my index_sequence in order to "unwrap" the index_sequence for calling std::get...
Is it possible to forego the intermediate call_foo function, and call foo directly?
That is, unwrap the tuple directly at the call-site?
If you don't want to or can't use std::apply, I can suggest a few alternatives.
The snippets below are based on the previous revision of your question that didn't have the class Bar in it. The same solutions work for the new revision as well.
(1) You could replace call_foo with a C++20 lambda with an explicit template parameter list:
#include <cstddef>
#include <iostream>
#include <tuple>
#include <utility>
template<typename... Ts>
void foo(const std::string& s, Ts... ts)
{
std::cout << "foo called with " << s << " and " << sizeof...(Ts) << " ts\n";
}
template<typename... Ts>
void bar(Ts... ts)
{
const std::string s = "hello world";
const auto t = std::make_tuple(ts...);
[&]<std::size_t ...I>(std::index_sequence<I...>)
{
foo(s, std::get<I>(t)...);
}
(std::make_index_sequence<std::tuple_size_v<decltype(t)>>{});
}
int main()
{
bar(1, 'a', 2.3);
}
Try it live
Unfortunately, GCC 8 currently seems to be the only major compiler that supports those.
(2) If your compiler doesn't have the new fancy lambdas, or you don't want to write the index_sequence boilerplate every time you need to expand the tuple, I suggest following:
#include <cstddef>
#include <iostream>
#include <tuple>
#include <utility>
template <std::size_t ...I, typename F> void with_sequence_impl(F &&func, std::index_sequence<I...>)
{
func(std::integral_constant<std::size_t, I>{}...);
}
template <std::size_t N, typename F> void with_sequence(F &&func)
{
with_sequence_impl(std::forward<F>(func), std::make_index_sequence<N>{});
}
template<typename... Ts>
void foo(const std::string& s, Ts... ts)
{
std::cout << "foo called with " << s << " and " << sizeof...(Ts) << " ts\n";
}
template<typename... Ts>
void bar(Ts... ts)
{
const std::string s = "hello world";
const auto t = std::make_tuple(ts...);
with_sequence<std::tuple_size_v<decltype(t)>>([&](auto ... i)
{
foo(s, std::get<i.value>(t)...);
});
}
int main()
{
bar(1, 'a', 2.3);
}
Try it live
I currently have a system to "connect" signals to functions. This signal is a variadic template that has as template parameters the arguments of the functions it can connect to.
In the current implementation, I obviously cannot connect to functions whose arguments aren't exactly the same (or those that can be converted to) as the signal's parameters. Now, as I'm trying to mimic Qt's signal/slot/connect, I'd also like to connect a signal of N parameters to a slot of M<N parameters, which is perfectly well-defined (i.e. ignore the >M parameters of the signal and just pass the first M to the connected function). For an example of the code I have in its most simplistic form, see Coliru.
So the question is two-fold:
How do I make the connect call work for a function void g(int);?
How do I make the emit call work for a function void g(int);?
I'm guessing I'll have to make some "magic" parameter pack reducer for both the slot and its call function, but I can't see how it all should fit together so it's quite hard to actually start trying to code a solution. I'm OK with a C++17-only solution, if at least Clang/GCC and Visual Studio 2015 can compile it.
The code linked above for completeness:
#include <memory>
#include <vector>
template<typename... ArgTypes>
struct slot
{
virtual ~slot() = default;
virtual void call(ArgTypes...) const = 0;
};
template<typename Callable, typename... ArgTypes>
struct callable_slot : slot<ArgTypes...>
{
callable_slot(Callable callable) : callable(callable) {}
void call(ArgTypes... args) const override { callable(args...); }
Callable callable;
};
template<typename... ArgTypes>
struct signal
{
template<typename Callable>
void connect(Callable callable)
{
slots.emplace_back(std::make_unique<callable_slot<Callable, ArgTypes...>>(callable));
}
void emit(ArgTypes... args)
{
for(const auto& slot : slots)
{
slot->call(args...);
}
}
std::vector<std::unique_ptr<slot<ArgTypes...>>> slots;
};
void f(int, char) {}
int main()
{
signal<int, char> s;
s.connect(&f);
s.emit(42, 'c');
}
template<class...> struct voider { using type = void; };
template<class... Ts> using voidify = typename voider<Ts...>::type;
template<class C, class...Args>
using const_lvalue_call_t = decltype(std::declval<const C&>()(std::declval<Args>()...));
template<class T, std::size_t...Is>
auto pick_from_tuple_impl(T &&, std::index_sequence<Is...>)
-> std::tuple<std::tuple_element_t<Is, T>...>;
template<class Tuple, class = std::enable_if_t<(std::tuple_size<Tuple>::value > 0)>>
using drop_last = decltype(pick_from_tuple_impl(std::declval<Tuple>(),
std::make_index_sequence<std::tuple_size<Tuple>::value - 1>()));
template<class C, class ArgsTuple, class = void>
struct try_call
: try_call<C, drop_last<ArgsTuple>> {};
template<class C, class...Args>
struct try_call<C, std::tuple<Args...>, voidify<const_lvalue_call_t<C, Args...>>> {
template<class... Ts>
static void call(const C& c, Args&&... args, Ts&&... /* ignored */) {
c(std::forward<Args>(args)...);
}
};
Then in callable_slot:
void call(ArgTypes... args) const override {
using caller = try_call<Callable, std::tuple<ArgTypes...>>;
caller::call(callable, std::forward<ArgTypes>(args)...);
}
For member pointer support (this requires SFINAE-friendly std::result_of), change const_lvalue_call_t to
template<class C, class...Args>
using const_lvalue_call_t = std::result_of_t<const C&(Args&&...)>;
then change the actual call in try_call::call to
std::ref(c)(std::forward<Args>(args)...);
This is poor man's std::invoke for lvalue callables. If you have C++17, just use std::invoke directly (and use std::void_t instead of voidify, though I like the sound of the latter).
Not sure to understand what do you exactly want but... with std::tuple and std::make_index_sequence ...
First of all you need a type traits that give you the number of arguments of a function (or std::function)
template <typename>
struct numArgs;
template <typename R, typename ... Args>
struct numArgs<R(*)(Args...)>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename R, typename ... Args>
struct numArgs<std::function<R(Args...)>>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
Next you have to add a constexpr value in callable_slot to memorize the number of arguments in the Callable function
static constexpr std::size_t numA { numArgs<Callable>::value };
Then you have to modify the call() method to pack the arguments in a std::tuple<ArgTypes...> and call another method passing the tuple and an index sequence from 0 to numA
void call(ArgTypes... args) const override
{ callI(std::make_tuple(args...), std::make_index_sequence<numA>{}); }
Last you have to call, in CallI(), the callable() function with only the first numA elements of the tuple of arguments
template <std::size_t ... Is>
void callI (std::tuple<ArgTypes...> const & t,
std::index_sequence<Is...> const &) const
{ callable(std::get<Is>(t)...); }
The following is a full working example
#include <memory>
#include <vector>
#include <iostream>
#include <functional>
template <typename>
struct numArgs;
template <typename R, typename ... Args>
struct numArgs<R(*)(Args...)>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename R, typename ... Args>
struct numArgs<std::function<R(Args...)>>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename ... ArgTypes>
struct slot
{
virtual ~slot() = default;
virtual void call(ArgTypes...) const = 0;
};
template <typename Callable, typename ... ArgTypes>
struct callable_slot : slot<ArgTypes...>
{
static constexpr std::size_t numA { numArgs<Callable>::value };
callable_slot(Callable callable) : callable(callable)
{ }
template <std::size_t ... Is>
void callI (std::tuple<ArgTypes...> const & t,
std::index_sequence<Is...> const &) const
{ callable(std::get<Is>(t)...); }
void call(ArgTypes... args) const override
{ callI(std::make_tuple(args...), std::make_index_sequence<numA>{}); }
Callable callable;
};
template <typename ... ArgTypes>
struct signal
{
template <typename Callable>
void connect(Callable callable)
{
slots.emplace_back(
std::make_unique<callable_slot<Callable, ArgTypes...>>(callable));
}
void emit(ArgTypes... args)
{ for(const auto& slot : slots) slot->call(args...); }
std::vector<std::unique_ptr<slot<ArgTypes...>>> slots;
};
void f (int i, char c)
{ std::cout << "--- f(" << i << ", " << c << ")" << std::endl; }
void g (int i)
{ std::cout << "--- g(" << i << ")" << std::endl; }
struct foo
{
static void j (int i, char c)
{ std::cout << "--- j(" << i << ", " << c << ")" << std::endl; }
void k (int i)
{ std::cout << "--- k(" << i << ")" << std::endl; }
};
int main ()
{
std::function<void(int, char)> h { [](int i, char c)
{ std::cout << "--- h(" << i << ", " << c << ")" << std::endl; }
};
std::function<void(int)> i { [](int i)
{ std::cout << "--- i(" << i << ")" << std::endl; }
};
using std::placeholders::_1;
foo foo_obj{};
std::function<void(int)> k { std::bind(&foo::k, foo_obj, _1) };
signal<int, char> s;
s.connect(f);
s.connect(g);
s.connect(h);
s.connect(i);
s.connect(foo::j);
s.connect(k);
s.emit(42, 'c');
}
This example need C++14 because use std::make_index_sequence and std::index_sequence.
Substitute both of they and prepare a C++11 compliant solution isn't really difficult.
My question is in the code:
template<typename... Ts>
struct TupleOfVectors {
std::tuple<std::vector<Ts>...> tuple;
void do_something_to_each_vec() {
//Question: I want to do this:
// "for each (N)": do_something_to_vec<N>()
//How?
}
template<size_t N>
void do_something_to_vec() {
auto &vec = std::get<N>(tuple);
//do something to vec
}
};
You can quite easily do that with some indices machinery. Given a meta-function gen_seq for generating compile-time integer sequences (encapsulated by the seq class template):
namespace detail
{
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { };
}
And the following function templates:
#include <tuple>
namespace detail
{
template<typename T, typename F, int... Is>
void for_each(T&& t, F f, seq<Is...>)
{
auto l = { (f(std::get<Is>(t)), 0)... };
}
}
template<typename... Ts, typename F>
void for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
detail::for_each(t, f, detail::gen_seq<sizeof...(Ts)>());
}
You can use the for_each_in_tuple function above this way:
#include <string>
#include <iostream>
struct my_functor
{
template<typename T>
void operator () (T&& t)
{
std::cout << t << std::endl;
}
};
int main()
{
std::tuple<int, double, std::string> t(42, 3.14, "Hello World!");
for_each_in_tuple(t, my_functor());
}
Here is a live example.
In your concrete situation, this is how you could use it:
template<typename... Ts>
struct TupleOfVectors
{
std::tuple<std::vector<Ts>...> t;
void do_something_to_each_vec()
{
for_each_in_tuple(t, tuple_vector_functor());
}
struct tuple_vector_functor
{
template<typename T>
void operator () (T const &v)
{
// Do something on the argument vector...
}
};
};
And once again, here is a live example.
Update
If you're using C++14 or later, you can replace the seq and gen_seq classes above with std::integer_sequence like so:
namespace detail
{
template<typename T, typename F, int... Is>
void
for_each(T&& t, F f, std::integer_sequence<int, Is...>)
{
auto l = { (f(std::get<Is>(t)), 0)... };
}
} // namespace detail
template<typename... Ts, typename F>
void
for_each_in_tuple(std::tuple<Ts...> const& t, F f)
{
detail::for_each(t, f, std::make_integer_sequence<int, sizeof...(Ts)>());
}
If you're using C++17 or later you can do this (from this comment below):
std::apply([](auto ...x){std::make_tuple(some_function(x)...);} , the_tuple);
In C++17 you can do this:
std::apply([](auto ...x){std::make_tuple(some_function(x)...);} , the_tuple);
given that some_function has suitable overloads for all the types in the tuple.
This already works in Clang++ 3.9, using std::experimental::apply.
In addition to the answer of #M. Alaggan, if you need to call a function on tuple elements in order of their appearance† in the tuple, in C++17 you can also use a fold expression like this:
std::apply([](auto& ...x){(..., some_function(x));}, the_tuple);
(live example).
†Because otherwise order of evaluation of function arguments is unspecified.
Here's one approach which may work well in your case:
template<typename... Ts>
struct TupleOfVectors {
std::tuple<std::vector<Ts>...> tuple;
void do_something_to_each_vec()
{
// First template parameter is just a dummy.
do_something_to_each_vec_helper<0,Ts...>();
}
template<size_t N>
void do_something_to_vec()
{
auto &vec = std::get<N>(tuple);
//do something to vec
}
private:
// Anchor for the recursion
template <int>
void do_something_to_each_vec_helper() { }
// Execute the function for each template argument.
template <int,typename Arg,typename...Args>
void do_something_to_each_vec_helper()
{
do_something_to_each_vec_helper<0,Args...>();
do_something_to_vec<sizeof...(Args)>();
}
};
The only thing that is a bit messy here is the extra dummy int template parameter to do_something_to_each_vec_helper. It is necessary to make the do_something_to_each_vec_helper still be a template when no arguments remain. If you had another template parameter you wanted to use, you could use it there instead.
If you are not particularly wedded to a solution in the form of generic
"for each" function template then you can use one like this:
#ifndef TUPLE_OF_VECTORS_H
#define TUPLE_OF_VECTORS_H
#include <vector>
#include <tuple>
#include <iostream>
template<typename... Ts>
struct TupleOfVectors
{
std::tuple<std::vector<Ts>...> tuple;
template<typename ...Args>
TupleOfVectors(Args... args)
: tuple(args...){}
void do_something_to_each_vec() {
do_something_to_vec(tuple);
}
template<size_t I = 0, class ...P>
typename std::enable_if<I == sizeof...(P)>::type
do_something_to_vec(std::tuple<P...> &) {}
template<size_t I = 0, class ...P>
typename std::enable_if<I < sizeof...(P)>::type
do_something_to_vec(std::tuple<P...> & parts) {
auto & part = std::get<I>(tuple);
// Doing something...
std::cout << "vector[" << I << "][0] = " << part[0] << std::endl;
do_something_to_vec<I + 1>(parts);
}
};
#endif // EOF
A test program, built with GCC 4.7.2 and clang 3.2:
#include "tuple_of_vectors.h"
using namespace std;
int main()
{
TupleOfVectors<int,int,int,int> vecs(vector<int>(1,1),
vector<int>(2,2),
vector<int>(3,3),
vector<int>(4,4));
vecs.do_something_to_each_vec();
return 0;
}
The same style of recursion can be used in a generic "for_each"
function template without auxiliary indices apparatus:
#ifndef FOR_EACH_IN_TUPLE_H
#define FOR_EACH_IN_TUPLE_H
#include <type_traits>
#include <tuple>
#include <cstddef>
template<size_t I = 0, typename Func, typename ...Ts>
typename std::enable_if<I == sizeof...(Ts)>::type
for_each_in_tuple(std::tuple<Ts...> &, Func) {}
template<size_t I = 0, typename Func, typename ...Ts>
typename std::enable_if<I < sizeof...(Ts)>::type
for_each_in_tuple(std::tuple<Ts...> & tpl, Func func)
{
func(std::get<I>(tpl));
for_each_in_tuple<I + 1>(tpl,func);
}
#endif //EOF
And a test program for that:
#include "for_each_in_tuple.h"
#include <iostream>
struct functor
{
template<typename T>
void operator () (T&& t)
{
std::cout << t << std::endl;
}
};
int main()
{
auto tpl = std::make_tuple(1,2.0,"Three");
for_each_in_tuple(tpl,functor());
return 0;
}
I was testing with tuples and metaprograming and found the current thread.
I think my work can inspire someone else although I like the solution of #Andy.
Anyway, just get fun!
#include <tuple>
#include <type_traits>
#include <iostream>
#include <sstream>
#include <functional>
template<std::size_t I = 0, typename Tuple, typename Func>
typename std::enable_if< I != std::tuple_size<Tuple>::value, void >::type
for_each(const Tuple& tuple, Func&& func)
{
func(std::get<I>(tuple));
for_each<I + 1>(tuple, func);
}
template<std::size_t I = 0, typename Tuple, typename Func>
typename std::enable_if< I == std::tuple_size<Tuple>::value, void >::type
for_each(const Tuple& tuple, Func&& func)
{
// do nothing
}
struct print
{
template<typename T>
void operator () (T&& t)
{
std::cout << t << std::endl;
}
};
template<typename... Params>
void test(Params&& ... params)
{
int sz = sizeof...(params);
std::tuple<Params...> values(std::forward<Params>(params)...);
for_each(values, print() );
}
class MyClass
{
public:
MyClass(const std::string& text)
: m_text(text)
{
}
friend std::ostream& operator <<(std::ostream& stream, const MyClass& myClass)
{
stream << myClass.m_text;
return stream;
}
private:
std::string m_text;
};
int main()
{
test(1, "hello", 3.f, 4, MyClass("I don't care") );
}
Boost mp11 has this functionality:
#include <iostream>
#include <string>
#include <boost/mp11.hpp>
using namespace std;
using boost::mp11::tuple_for_each;
std::tuple t{string("abc"), 47 };
int main(){
tuple_for_each(t,[](const auto& x){
cout << x + x << endl;
});
}
Could you help me in fixing the compile error in the following code:
#include <sstream>
#include <iostream>
using namespace std;
template<typename T, typename ...P>
class Mystrcat{
public:
Mystrcat(T t, P... p){init(t,p...);}
ostringstream & get(){return o;}
private:
ostringstream o;
void init(){}
void init(T t, P... p);
};
template<typename T, typename ...P>
void Mystrcat<T,P...>::init(T t, P ...p){
o << t;
if (sizeof...(p)) init(p...);
}
int main(){
Mystrcat<char*,char *> m("Amma","Namasivayah");
cout << m.get().str();
}
I get the error, no matching function for call to
‘Mystrcat<char*, char*>::init(char*&)’
note: candidates are:
void Mystrcat<T, P>::init() [with T = char*, P = char*]
void Mystrcat<T, P>::init(T, P ...) [with T = char*, P = char*]
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
Thanks
suresh
You're getting this error because there isn't a way to unpack your p into either init function. In your instantiation Mystrcat<char*, char *>, unpacking a P... will yield a single thing in the type: char*, which doesn't have an init with that signature (the instantiated version will have a void init() and void init(char*, char*), whereas you are trying to call init(char*)).
In fact, your template is impossible to instantiate, since init will always take one more argument than you give it in void Mystrcat<T,P...>::init(T t, P ...p). If you change the definition to call what you have defined:
template<typename T, typename ...P>
void Mystrcat<T,P...>::init(T t, P ...p){
o << t;
if (sizeof...(p)) init(t, p...);
}
then this will work (at least in g++-4.5.2).
EDIT: I think this is what you're actually looking for:
#include <sstream>
#include <iostream>
class MyCollector
{
public:
template <typename... T>
explicit MyCollector(const T&... args)
{
init(args...);
}
std::string str()
{
return _stream.str();
}
private:
void init()
{ }
template <typename First, typename... Rest>
void init(const First& first, const Rest&... rest)
{
_stream << first;
init(rest...);
}
std::ostringstream _stream;
};
int main()
{
MyCollector collector("Whatever ", "stuff like ", 2, " or ", 3.14, "\n");
std::cout << collector.str();
return 0;
}