How do I make the method name (here some_method) a template parameter?
template<typename T>
void sv_set_helper(T& d, bpn::array const& v) {
to_sv(v, d.some_method());
}
There is no such thing as a 'template identifier parameter', so you can't pass names as parameters. You could however take a member function pointer as argument:
template<typename T, void (T::*SomeMethod)()>
void sv_set_helper(T& d, bpn::array const& v) {
to_sv(v, ( d.*SomeMethod )());
}
that's assuming the function has a void return type. And you will call it like this:
sv_set_helper< SomeT, &SomeT::some_method >( someT, v );
Here is a simple example...
#include <iostream>
template<typename T, typename FType>
void bar(T& d, FType f) {
(d.*f)(); // call member function
}
struct foible
{
void say()
{
std::cout << "foible::say" << std::endl;
}
};
int main(void)
{
foible f;
bar(f, &foible::say); // types will be deduced automagically...
}
Related
How to pass a const member function as a non-const member function to the template?
class TestA
{
public:
void A() {
}
void B() const {
}
};
template<typename T, typename R, typename... Args>
void regFunc(R(T::*func)(Args...))
{}
void test()
{
regFunc(&TestA::A); // OK
regFunc(&TestA::B); // ambiguous
}
Don't want to add something like:
void regFunc(R(T::*func)(Args...) const)
Is there a better way?
Why not simply pass it to a generic template function:
see live
#include <iostream>
#include <utility>
class TestA
{
public:
void A() { std::cout << "non-cost\n"; }
void B() const { std::cout << "cost with no args\n"; }
void B2(int a) const { std::cout << "cost with one arg\n"; }
const void B3(int a, float f) const { std::cout << "cost with args\n"; }
};
template<class Class, typename fType, typename... Args>
void regFunc(fType member_fun, Args&&... args)
{
Class Obj{};
(Obj.*member_fun)(std::forward<Args>(args)...);
}
void test()
{
regFunc<TestA>(&TestA::A); // OK
regFunc<TestA>(&TestA::B); // OK
regFunc<TestA>(&TestA::B2, 1); // OK
regFunc<TestA>(&TestA::B3, 1, 2.02f); // OK
}
output:
non-cost
cost with no args
cost with one arg: 1
cost with args: 1 2.02
No, you have to specify the cv and ref qualifiers to match. R(T::*func)(Args...) is a separate type to R(T::*func)(Args...) const for any given R, T, Args....
As a terminology note, it isn't ambiguous. There is exactly one candidate, it doesn't match. Ambiguity requires multiple matching candidates.
For example, given the following code
class A {
public:
double operator()(double foo) {
return foo;
}
};
class B {
public:
double operator()(double foo, int bar) {
return foo + bar;
}
};
I want to write two versions of fun, one that works with objects with A's signature and another one that works with objects with B's signature:
template <typename F, typename T>
T fun(F f, T t) {
return f(t);
}
template <typename F, typename T>
T fun(F f, T t) {
return f(t, 2);
}
And I expect this behavior
A a();
B b();
fun(a, 4.0); // I want this to be 4.0
fun(b, 4.0); // I want this to be 6.0
Of course the previous example throws a template redefinition error at compile time.
If B is a function instead, I can rewrite fun to be something like this:
template <typename T>
T fun(T (f)(T, int), T t) {
return f(t, 2);
}
But I want fun to work with both, functions and callable objects. Using std::bind or std::function maybe would solve the problem, but I'm using C++98 and those were introduced in C++11.
Here's a solution modified from this question to accommodate void-returning functions. The solution is simply to use sizeof(possibly-void-expression, 1).
#include <cstdlib>
#include <iostream>
// like std::declval in c++11
template <typename T>
T& decl_val();
// just use the type and ignore the value.
template <std::size_t, typename T = void>
struct ignore_value {typedef T type;};
// This is basic expression-based SFINAE.
// If the expression inside sizeof() is invalid, substitution fails.
// The expression, when valid, is always of type int,
// thanks to the comma operator.
// The expression is valid if an F is callable with specified parameters.
template <class F>
typename ignore_value<sizeof(decl_val<F>()(1),1), void>::type
call(F f)
{
f(1);
}
// Same, with different parameters passed to an F.
template <class F>
typename ignore_value<sizeof(decl_val<F>()(1,1),1), void>::type
call(F f)
{
f(1, 2);
}
void func1(int) { std::cout << "func1\n"; }
void func2(int,int) { std::cout << "func2\n"; }
struct A
{
void operator()(int){ std::cout << "A\n"; }
};
struct B
{
void operator()(int, int){ std::cout << "B\n"; }
};
struct C
{
void operator()(int){ std::cout << "C1\n"; }
void operator()(int, int){ std::cout << "C2\n"; }
};
int main()
{
call(func1);
call(func2);
call(A());
call(B());
// call(C()); // ambiguous
}
Checked with gcc and clang in c++98 mode.
The following example works with passing a member function pointer with no arguments. Can someone explain me how to do this with arguments? If it is possible can we also pass variable number of arguments?
class test {
public:
typedef void (test::*check_fun_type)();
//typedef void (test::*check_fun_type)(int);
void mF1(check_fun_type ptr);
void check1();
void check2(int v1);
};
void test::check1() {
std::cout << "check1" << std::endl;
}
void test::check2(int v1) {
std::cout << "check2 " << v1 << std::endl;
}
void test::mF1(check_fun_type ptr) {
(this->*ptr)();
}
int main() {
test t1;
t1.check1();
t1.check2(2);
t1.mF1(&test::check1);
//t1.mF1((&test::check2)(2));
}
No, you can only pass the arguments when calling it. Such as:
void test::mF1(check_fun_type ptr) {
(this->*ptr)(2);
}
EDIT
You can use std::bind to invoke function with some of its parameters bound to arguments in advance, such as:
test t1;
auto f = std::bind(&test::check2, &t1, 2);
f();
For your case, you need to change the parameter type of test::mF1 to std::function. Such as:
typedef std::function<void(test*)> check_fun_type;
and
void test::mF1(check_fun_type ptr) {
ptr(this);
}
int main() {
test t1;
t1.mF1(std::bind(&test::check2, _1, 2));
}
DEMO
In C++11 you could use
template <class F, class... Args>
void mFx(F ptr, Args... args)
{
(this->*ptr)(args...);
}
to pass member function pointer of any type and variable number of arguments.
In C++98 similar functionality can be achieved by overloading methods for each number of arguments
template <class F>
void mFx(F ptr)
{
(this->*ptr)();
}
template <class F, class A1>
void mFx(F ptr, A1 a1)
{
(this->*ptr)(a1);
}
template <class F, class A1, class A2>
void mFx(F ptr, A1 a1, A2 a2)
{
(this->*ptr)(a1, a2);
}
I am trying to implement a vector that can take elements of several types, and can apply a function on all of them. This is easily done with a base class, virtual functions and inheritance, but I explicity do not want to use it. Here is how far I am so far:
#include <iostream>
#include <vector>
#include <tuple>
// this will be my new polymorphic vector;
template<typename... Ts>
class myvector {
std::tuple<std::vector<Ts>...> vectors;
template <template<typename> class funtype>
void for_each() {
}
template <template<typename> class funtype, typename X, typename... Xs>
void for_each() {
std::vector<X>& vector = std::get<std::vector<X>>(vectors);
for ( X& x : vector ) {
funtype<X> fun;
fun(x);
}
for_each<funtype, Xs...>();
}
public:
template <typename T>
void push_back(const T& t) {
std::vector<T>& vector = std::get<std::vector<T>>(vectors);
vector.push_back(t);
}
template <typename T>
void pop_back() {
std::vector<T>& vector = std::get<std::vector<T>>(vectors);
vector.pop_back();
}
/* here I would like to pass a function, or function object that
* can be expanded to all underlying types. I would prefer to just
* give a function name, that has an implementation to all types in Ts
*/
template <template<typename> class funtype>
void ForEach() {
for_each<funtype,Ts...>();
}
};
struct foo {
};
struct bar {
};
template <typename T>
void method(T& t);
template<>
void method(foo& b) {
std::cout << "foo" << std::endl;
}
template<>
void method(bar& b) {
std::cout << "bar" << std::endl;
}
int main()
{
myvector<foo,bar> mv;
mv.push_back( foo{} );
mv.push_back( bar{} );
mv.ForEach<method>();
}
at the moment I am kind of stuck, I hope you can give me some advise on how to go further.
A common solution is to use a function object with a set of operator():
struct my_fun_type
{
void operator()(foo&) const
{ std::cout << "foo\n"; }
void operator()(bar&) const
{ std::cout << "bar\n"; }
};
This allows to pass a "set" of overloaded functions to an algorithm, state, and is rather convenient to use:
my_algorithm(my_fun_type{});
If we want to add support for such function objects, we could define ForEach as follows:
template <typename Elem, typename Fun>
void for_each(Fun&& fun) {
std::vector<Elem>& vector = std::get<std::vector<Elem>>(vectors);
for ( Elem& e : vector ) {
fun(x);
}
}
template <typename Fun>
void ForEach(Fun&& fun) {
int dummy[] = { 0, (for_each<Ts>(fun), 0)... };
(void)dummy;
}
That dummy is a trick to call for_each for all types in Ts. The (void)dummy is intended to suppress a compiler warning (dummy is never read from).
You can learn more about this technique in other Q&As, such as that one.
The Fun&& is not an rvalue reference, but a universal reference.
Note that the above example differs from many Standard Library algorithms, which take the function object by value:
template <typename Elem, typename Fun>
void for_each(Fun fun) {
std::vector<Elem>& vector = std::get<std::vector<Elem>>(vectors);
std::for_each(vector.begin(), vector.end(), std::move(fun));
}
template <typename Fun>
void ForEach(Fun fun) {
int dummy[] = { 0, (for_each<Ts>(fun), 0)... };
(void)dummy;
}
To pass a set of overloaded free functions, we can wrap them in a function object (thank #Yakk for the suggestion):
struct method_t
{
template<class... Ts>
void operator()(Ts&&... ts) const
{ method( std::forward<Ts>(ts)... ); }
};
In C++1y, such a function object type can be created with less boilerplate using a polymorphic lambda:
[](auto&&... pp)
{ method( std::forward<decltype(pp)>(pp)... ); }
I need a function wrapper for std::bind that will be called before the function it's wrapper, passing the arguments along to the wrapped functions.
std::function<void (int)> foo = postbind<int>(service, handle);
I've so far got down to that
std::function<void (int)> foo = postbind(service, handle);
How can I remove that template parameter? It seems to come down to the type deduction from the object generation function (postbind) not being intelligent enough.
#include <functional>
template<typename T>
void foo(std::function<void (T)> func)
{
}
void handler(int x)
{
}
int main()
{
foo(handler);
return 0;
}
Says error: no matching function for call to 'foo(void (&)(int))'
Yet, the code sample:
template<typename T>
void foo(T t)
{
}
int main()
{
foo(99);
return 0;
}
This works. Any ideas how to make this work? I need to be able to pass std::bind to it and have the result cast successfully to std::function.
How can I remove the template parameters? Thanks.
Q. What is service and this class meant to do?
A. Encapsulate a function wrapper that boost::asio::io_service->posts out of the current thread.
Full sourcecode:
#include <iostream>
#include <functional>
#include <memory>
class io_service
{
};
typedef std::shared_ptr<io_service> service_ptr;
template <typename Arg1>
class postbind_impl_1
{
public:
typedef std::function<void (Arg1)> function;
postbind_impl_1(service_ptr service, function memfunc)
: service_(service), memfunc_(memfunc)
{
}
void operator()(Arg1 arg1)
{
// do stuff using io_service
memfunc_(arg1);
}
private:
service_ptr service_;
function memfunc_;
};
template <typename Arg1>
postbind_impl_1<Arg1> postbind(service_ptr service,
typename postbind_impl_1<Arg1>::function handle)
{
return postbind_impl_1<Arg1>(service, handle);
}
// ----------------
void handle(int x)
{
std::cout << x << "\n";
}
int main()
{
service_ptr service;
std::function<void (int)> foo = postbind(service, handle);
foo(110);
return 0;
}
AFAICT argument types of a bind expression are not deducible, so what you want is pretty much impossible.
How do you expect the compiler to know to use std::function? In this code:
#include <functional>
template<typename T>
void foo(T func)
{
}
void handler(int x)
{
}
int main()
{
foo(handler);
return 0;
}
T is NOT std::function<void (int)>. It's void (&)(int) (like the error message said), a reference to a function, not a functor object.
Deduction of the argument type of the passed function should work, try:
#include <functional>
template<typename T>
std::function<void (T)> foo(void (*func)(T))
{
}
void handler(int x)
{
}
int main()
{
foo(handler);
return 0;
}
Demo: http://ideone.com/NJCMS
If you need to extract argument types from either std::function or a plain function pointer, you'll need a helper structure:
template<typename>
struct getarg {};
template<typename TArg>
struct getarg<std::function<void (TArg)>> { typedef TArg type; };
template<typename TArg>
struct getarg<void (*)(TArg)> { typedef TArg type; };
template<typename TArg>
struct getarg<void (&)(TArg)> { typedef TArg type; };
template<typename T>
std::function<void (typename getarg<T>::type)> foo(T func)
{
}
void handler(int x)
{
}
int main()
{
foo(handler);
return 0;
}
Demo: http://ideone.com/jIzl7
With C++0x, you can also match anything that implicitly converts to std::function, including return values from std::bind and lambdas: http://ideone.com/6pbCC
I'm not entirely sure what you're trying to achieve, but here's a naive wrapper that stores a list of actions:
template <typename R, typename A>
struct wrap
{
typedef std::function<R(A)> func;
wrap(func f_) : f(f_) { }
void prebind(func g) { prebound.push_back(g); }
R operator()(A arg)
{
for (auto it = prebound.cbegin(); it != prebound.cend(); ++it)
{
func g = *it;
g(arg);
}
f(arg);
}
private:
std::vector<func> prebound;
func f;
};
wrap<void, int> make_wrap(std::function<void(int)> f)
{
return wrap<void, int>(f);
}
Usage:
auto foowrap = make_wrap(foo);
foowrap.prebind(std::function<void(int)>(action1);
foowrap.prebind(std::function<void(int)>(action2);
foowrap(12); // calls action1(12), action2(12), foo(12)
To all the naysayers who said this wasn't possible :)
/*
* Defines a function decorator ala Python
*
* void foo(int x, int y);
* function<void ()> wrapper(function<void (int)> f);
*
* auto f = decorator(wrapper, bind(foo, 110, _1));
* f();
*/
#include <functional>
template <typename Wrapper, typename Functor>
struct decorator_dispatch
{
Wrapper wrapper;
Functor functor;
template <typename... Args>
auto operator()(Args&&... args)
-> decltype(wrapper(functor)(std::forward<Args>(args)...))
{
return wrapper(functor)(std::forward<Args>(args)...);
}
};
template <typename Wrapper, typename Functor>
decorator_dispatch<
Wrapper,
typename std::decay<Functor>::type
>
decorator(Wrapper&& wrapper, Functor&& functor)
{
return {wrapper, functor};
}