Having guard class on C++11 that is responsible to invoke some member function on scope exit:
template <class T, void (T::*op)()>
struct Guard
{
Guard(T*g):
_g(g){}
~Guard()
{
(_g->*op)();
}
T*_g;
};
Usage is very simple:
typedef Guard<Foo, &Foo::bar> FooGuard;
...
FooGuard g(&foo);
My question originated from existing shared_ptr<Foo>. How to create specialization that keeps shared_ptr<T> instead of T*
What I've already tried:
template <class T, void (T::*op)()>
struct Guard<std::shared_ptr<T>, op>
{
Guard(std::shared_ptr<T>& g):
_g(g){}
~Guard()
{
((*_g).*op)();
}
std::shared_ptr<T> _g;
};
But during compilation on G<std::shared_ptr<Foo>, &Foo::bar> g2(foo); have foreseeable got:
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'void (__thiscall std::shared_ptr::* )(void)'
as #PiotrSkotnicki already pointed out, your specialization is not valid.
You could use something like the following, however the interface does not look that nice:
template <class T, class U, void (U::*op)()>
struct Guard
{
Guard(T*g):
_g(g){}
~Guard()
{
std::cout << "normal guard" << std::endl;
(_g->*op)();
}
T*_g;
};
template <class T, class U, void (U::*op)()>
struct Guard<std::shared_ptr<T>, U, op>
{
Guard(std::shared_ptr<T>& g):
_g(g){}
~Guard()
{
std::cout << "shared_ptr guard" << std::endl;
((*_g).*op)();
}
std::shared_ptr<T> _g;
};
Demo:
struct Foo
{
void bar()
{
std::cout << "Foo::bar()" << std::endl;
}
};
int main()
{
Foo foo;
{
typedef Guard<Foo, Foo, &Foo::bar> FooGuard;
FooGuard g(&foo);
}
std::shared_ptr<Foo> foo_ptr = std::make_shared<Foo>();
{
typedef Guard<std::shared_ptr<Foo>, Foo, &Foo::bar> FooGuard;
FooGuard g(foo_ptr);
}
return 0;
}
Output:
normal guard
Foo::bar()
shared_ptr guard
Foo::bar()
live example
I would suggest using lambda functions instead and capture by value:
#include <functional>
#include <memory>
struct Guard
{
typedef std::function<void()> func_type;
Guard( const func_type& f ): func(f) {}
~Guard() { if (func) func(); }
func_type func;
};
struct Foo
{
void bar() {}
};
int main()
{
auto foo_ptr = std::make_shared<Foo>();
Guard g([foo_ptr](){ foo_ptr->bar(); }); // note the capture by value
}
Note that you are free to capture by reference too, if you want to guard an instance allocated on the stack for example.
If you really want to stick to the ugly way, I would suggest using deleters:
#include <string>
#include <memory>
#include <cstdio>
template < class T, void (T::*op)() >
struct Guard
{
Guard( T *p ): ptr( p, [](T*){} ) {}
Guard( const std::shared_ptr<T>& p ): ptr(p) {}
~Guard() { if (ptr) ((*ptr).*op)(); }
std::shared_ptr<T> ptr;
};
struct Foo
{
Foo( const char* n ): name(n) {}
void bar() { printf("Hello from %s\n",name.c_str()); }
std::string name;
};
int main()
{
auto foo1 = Foo("Bob");
auto foo2 = std::make_shared<Foo>("Alice");
Guard<Foo,&Foo::bar> g1(&foo1), g2(foo2);
}
Related
In my TClass<T>::foo() function, I'd like to invoke a T instance if and only if T is a function type.
#include <iostream>
#include <functional>
template<class T>
struct TClass
{
TClass(T value) : value(value) {}
T value;
void foo()
{
// if(value is std::function)
// call function;
}
};
int main()
{
TClass<int> t1{0};
t1.foo();
TClass<std::function<void()>> t2{[](){ std::cout << "Hello, World!\n"; }};
t2.foo();
}
How can I do that?
In C++11, the easiest way to do this is to re-deduce the value through a helper function:
template <typename U>
auto foo_helper(U const& f, int) -> decltype(f()) {
return f();
}
template <typename U>
void foo_helper(U const&, long) {}
void foo() {
foo_helper(value, 0);
}
The conversion from 0 to int is better than its conversion to long, so if the first overload is viable - it will be preferred. If the first overload isn't viable, then we call the second one.
If you really care only about std::function, then we can just have simpler overloads:
void foo_helper(std::function<void()> const& f) {
f();
}
template <typename T>
void foo_helper(T const&) { }
void foo() {
foo_helper(value);
}
In C++17 you can do:
void foo() {
if constexpr (std::is_invocable_v<T>) {
value();
}
}
If you only wants to allow std::function, you'll need your own trait, e.g.:
template <class T>
struct is_stdfunction: std::false_type {};
template <class T>
struct is_stdfunction<std::function<T>: std::true_type {};
template <class T>
constexpr bool is_stdfunction_v = is_stdfunction<T>::value;
// Then in foo():
void foo() {
if constexpr (is_stdfunction_v<std::decay_t<T>>) {
value();
}
}
Why not partial specialization ?
Consider:
#include <iostream>
#include <functional>
template<class T>
struct TClass {
TClass(T value) : value(value) {}
T value;
void foo() {
std::cout << "T - other" << std::endl;
}
};
template<class T>
struct TClass<std::function<T>> {
TClass(std::function<T> value) : value(value) {}
std::function<T> value;
void foo() {
std::cout << "std::function" << std::endl;
}
};
Consider the following, minimal example:
struct S {
using func_t = void(*)(void *);
template<typename T>
static void proto(void *ptr) {
static_cast<T*>(ptr)->f();
}
func_t func;
void *ptr;
};
struct T {
void f() {}
};
void g(S &s) {
s.func(s.ptr);
}
int main() {
T t;
S s;
s.func = &S::proto<T>;
s.ptr = &t;
g(s);
}
The pretty obvious idea is to erase the type of a bunch of objects (like T, that is not the only available type) to create an array of instances of S, then iterate over that array and invoke a predetermined member function.
So far so good, it's easy to implement and it works.
Now I would like to provide an external function to be invoked on the erased object, something that would be like this:
template<typename T, typename F>
static void proto(void *ptr, F &&f) {
auto *t = static_cast<T*>(ptr);
std::forward<F>(f)(*t);
t->f();
}
Or this:
template<typename T>
static void proto(void *ptr, void(*f)(T &)) {
auto *t = static_cast<T*>(ptr);
f(*t);
t->f();
}
To be invoked as:
s.func(s.ptr, [](auto obj){ /* ... */ });
A kind of template method pattern where the extra functionalities are provided by the caller instead of a derived class.
Unfortunately I cannot do that for I cannot reduce the specializations to something homogeneous to be assigned to a function pointer.
The only alternative I can see is to define a custom class like the following one:
struct C {
template<typename T>
void f(T &t) { /* ... */ }
// ...
};
Where f dispatches somehow the call internally to the right member function, then use it as:
struct S {
using func_t = void(*)(void *, C &);
template<typename T>
static void proto(void *ptr, C &c) {
auto t = static_cast<T*>(ptr);
c.f(*t);
t->f();
}
func_t func;
void *ptr;
};
That is not far from what I would do by using a lambda, but it's more verbose and requires me to explicitly declare the class C.
Is there any other valid alternative to achieve the same or is this the only viable solution?
Assuming you can enumerate the types you wish to support you can do this:
#include <iostream>
#include <string>
#include <vector>
template <class... Ts>
struct PseudoFunction {
private:
template <class T>
static void (*function)(T &);
template <class T>
static void call_func(void *object) {
return function<T>(*static_cast<T *>(object));
}
template <class Fun>
static void assign(Fun) {}
template <class Fun, class Head, class... Tail>
static void assign(Fun fun) {
function<Head> = fun;
assign<Fun, Tail...>(fun);
}
public:
template <class T>
PseudoFunction(T *t)
: object(t)
, func(call_func<T>) {}
template <class F>
static void set_function(F f) {
assign<F, Ts...>(f);
}
void operator()() {
func(object);
}
private:
void *object;
void (*func)(void *);
};
template <class... Ts>
template <class T>
void (*PseudoFunction<Ts...>::function)(T &) = nullptr;
//example types that are not related and not copy constructible
//but have the same member function name and signature
struct T1 {
T1() = default;
T1(const T1 &) = delete;
void func(double d) {
std::cout << "T1: " + std::to_string(d) + '\n';
}
};
struct T2 {
T2() = default;
T2(const T2 &) = delete;
void func(double d) {
std::cout << "T2: " + std::to_string(d) + '\n';
}
};
int main() {
T1 t1;
T2 t2;
using PF = PseudoFunction<T1, T2>;
std::vector<PF> funcs;
funcs.push_back(&t1);
funcs.push_back(&t2);
PF::set_function([](auto &object) { object.func(3.14); });
for (auto &f : funcs) {
f();
}
}
(demo)
It has decent call syntax (just that you have to specify the function before calling the objects) and some overhead of setting potentially unused function pointers.
One could probably make a wrapper that does the set_function and iterating over the PFs in one go.
I don't know if this is possible, but I would like to understand better how this works.
Can a class implict convertsion operation be used to match a template parameter?
This is what I want to do.
#include <iostream>
template<typename T>
struct Value {
};
template<>
struct Value<int> {
static void printValue(int v) {
std::cout << v << std::endl;
}
};
struct Class1 {
int value;
};
/*
template<>
struct Value<Class1*> {
static void printValue(Class1* v) {
std::cout << v->value << std::endl;
}
};
*/
template<typename X>
struct ClassContainer {
ClassContainer(X *c) : _c(c) {}
operator X*() { return _c; }
X *_c;
};
template<typename X>
struct Value<ClassContainer<X>> {
static void printValue(ClassContainer<X> v) {
std::cout << static_cast<X*>(v)->value << std::endl;
}
};
template<typename X>
void doPrintValue(X v)
{
Value<X>::printValue(v);
}
int main(int argc, char *argv[])
{
doPrintValue(10);
Class1 *c = new Class1{ 20 };
//doPrintValue(c); // error C2039: 'printValue': is not a member of 'Value<X>'
ClassContainer<Class1> cc(c);
doPrintValue(cc);
std::cout << "PRESS ANY KEY TO CONTINUE";
std::cin.ignore();
}
ClassContainer has an implict conversion to X*. Is it possible to match ClassContainer passing only X*?
If you want the template class for pointers to behave like the template class for something else, just inherit:
template<typename T>
struct Value<T*> : Value<ClassContainer<T>> {};
It will inherit the public printValue function, which accepts a parameter that can be constructed from T*, and everything will be implicitly converted as expected.
See it all live here.
I was trying to use a functor as a std::function object inside a class template. Below is what I have done so far.
//! the functor class template
template<typename T>
struct func
{
void operator ()(T t)
{
std::cout << t << "\n";
}
};
//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
std::function<void(T)> bar = func<T>();
};
int main()
{
Foo<int> foo;
return 0;
}
It was complained that
error: conversion from 'func<int>' to non-scalar type 'std::function<void(int)>' requested
struct Foo
^
Is it possible to do so? How to fix it?
You can either make it static and initialize it outside class-scope, or initialize it in the constructor. Tested on GCC 4.7.2.
template<typename T>
struct Foo
{
static std::function<void(T)> bar;
};
template <typename T>
std::function<void(T)> Foo<T>::bar = func<T>();
EDIT
In C++11, you can also use brace-initialization:
std::function<void(T)> bar { func<T>() };
Different ways to use std::function in a non-static data member initializer
#include <functional>
#include <iostream>
#define ENABLE_CONVERSION 1
template<typename T>
struct func
{
void operator ()(T t)
{
std::cout << "Function: " << t << "\n";
}
#if ENABLE_CONVERSION
// FIX: error: conversion from ‘func<int>’ to non-scalar type
// ‘std::function<void(int)>’ requested
operator std::function<void(T)> () { return std::function<void(T)>(*this); }
#endif
};
template<typename T>
struct Foo
{
std::function<void(T)> bar0 = std::function<void(T)>(func<T>());
std::function<void(T)> bar1{func<T>()};
// Error without ENABLE_CONVERSION
std::function<void(T)> bar2 = func<T>();
static std::function<void(T)> bar3;
void operator() () {
bar0(0);
bar1(1);
bar2(2);
bar3(3);
}
};
template<typename T>
std::function<void(T)> Foo<T>::bar3 = func<T>();
template<typename T>
void goo() {
// This compiles without ENABLE_CONVERSION:
// What is the difference to non-static data member initializers ?
std::function<void(T)> g = func<T>();
g(4);
}
int main()
{
Foo<int> foo;
foo();
goo<int>();
return 0;
}
Additional question
I tried to find differences between variable brace-or-equal-initializer
and the non-static data member brace-or-equal-initializer. I found nothing.
What is the difference between
std::function<void(T)> bar2 = func<T>();
and
std::function<void(T)> g = func<T>();
when ENABLE_CONVERSION is zero?
In your case std::function is optional, use direct functor itself.
//! the functor class template
template<typename T>
struct func
{
void operator ()(T t)
{
std::cout << t << "\n";
}
};
//! the class template that holds a std::function object as a member
template<typename T>
struct Foo
{
//std::function<void(T)> bar = func<T>(); <-- **removed, because std::function isn't cheap as func<T>**.
func<T> bar;//default initialized itself.
};
int main()
{
Foo<int> foo;
foo.bar(24);//prints 24.
return 0;
}
EDIT:
In common case, move template from struct declration to the operator, i.e. as:
struct func
{
template< typename T >
void operator()(T t ) const { std::cout << t << '\n'; }
};
struct Foo
{
func m_func;
};
int main(){
Foo f;
f.m_func(24); // prints 24
f.m_func("hello world"); // prints "hello world"
f.m_func(3.143); // prints 3.143
// and etc.,
};
in c++14, std::less<>, std::greater<> and more other functors template keyword moved to the operator declaration, instead of struct declaration, it's help more generic comparation.
Edit2: You may use following technicus:
struct func{
template< typename T > void operator()(T t) const{ std::cout << t << '\n';}
};
template< typename T, typename Functor> // Functor as template
struct Foo
{
Functor m_Functor; //--> functor member
T m_Data; // or something else.
};
// create `makeFoo` for auto deduced functor type.
template< typename T, typename Functor>
Foo<T,Functor> makeFoo(Functor f, T t ) { return {f,t}; }
int print(int i, int j){ std::cout << i+j << '\n' ;}
int main()
{
auto foo = makeFoo(24, func{} );
// use foo
auto foo2 = makeFoo("hello", std::bind(print, 2, _1) );
// use foo2
}
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};
}