Is it possible to declare a function bar to have the same signature as function foo?
int foo(int a)
{
return 0;
}
decltype(foo) bar
{
return 1;
} //imaginary syntax
I think the same applies as for typedefs and aliases: You may use decltype to declare a function, but not to define it:
int foo();
decltype(foo) bar;
int foo()
{
return bar();
}
int bar() { return 0; }
is accepted by clang++3.5 and g++4.8.1
[dcl.fct.def.general]/2 forbids (grammatically) the definition of a function w/o parentheses:
The declarator in a function-definition shall have the form
D1 ( parameter-declaration-clause ) cv-qualifier-seqopt
ref-qualifieropt exception-specificationopt attribute-specifier-seqopt trailing-return-typeopt
as described in 8.3.5.
You can use variadic templates to define a function which has the same signature as any function:
#include <iostream>
int foo(char const *blah) { return 0; }
template<typename... Args>
auto bar(Args ... args) -> decltype(foo(args...))
{
return 1;
}
int main() {
std::cout << foo("test") << std::endl;
std::cout << bar("test") << std::endl;
return 0;
}
This could also be modified slightly to pass "foo" as the first template argument, so that you could use the same "bar" with many different "foo"s:
template<typename Func, typename... Args>
auto bar(Func f, Args ... args) -> decltype(f(args...))
{
return 1;
}
int baz(double d) { return 3; }
int main() {
std::cout << bar(&foo, "test") << std::endl;
std::cout << bar(&baz, 1.2) << std::endl;
return 0;
}
The first thing that comes into mind is that you need to name the parameters so no, you can't.
The type of foo is:
int(int)
so any imaginary declaration syntax like:
decltype(foo) bar { //imaginary syntax
// can't access parameter
return 1;
}
will have the problem that bar can't access parameters.
So the best you can do is what #dyp suggests.
One other thing you could do is to check if two functions have the same signature:
static_assert(std::is_same<decltype(foo), decltype(bar)>::value, "Invalid bar signature");
Not trivially as you're posing, since you cannot set the arguments directly. decltype(foo) does return the actual type of foo, so you can use that to instantiate a template traits class that then exposes the return type and arguments type (somehow), and then use that to define your function.
#include <stdio.h>
int sf(int, float, double, bool) {}
template <typename RV, typename... args>
RV func(args... as) {
printf("%d %f %f %d\n", as...);
return sf(as...);
}
template <typename RV, typename... args>
RV(*generateFunc(RV(*)(args...)))(args...) {
return &func<RV, args...>;
}
int main() {
decltype(sf) *f = generateFunc(sf);
f(42, 1.0f, 12.0, true);
}
This generates a function to match sf's signature and then forwards the call to it.
Related
I need to do something like this:
template<class A=B, class B>
A fn(B x) { return A(x); };
int main()
{
int i = fn(5); // Error, no matching overload found
double d = fn<double>(5);
};
Hence, a function template which deduces the types automatically from the function arguments, but the caller can change the first one if needed. Any way to do this?
You can simply use constexpr if in such cases like:
struct NO_TYPE;
template<class RET_TYPE = NO_TYPE, class IN_TYPE>
auto fn(IN_TYPE x)
{
if constexpr ( std::is_same_v< RET_TYPE, NO_TYPE> )
{
std::cout << "1" << std::endl;
return IN_TYPE(x);
}
else
{
std::cout << "2" << std::endl;
return RET_TYPE(x);
}
}
int main()
{
int i = fn(5); // Error, no matching overload found
double d = fn<double>(5);
};
What I'm trying to achieve is creating a struct which stores any kind of method. I can later call struct_object.run() to run the method I've stored.
This method can return any kind of value and, most importantly, use any amount of parameters; however, I can't get around the "any amount of parameters" issue.
Mind you, the following code doesn't even build, mostly because I have no clue on what the correct syntax would be like.
ApplicationPair.h
template<typename T, typename... Args>
struct ApplicationPair
{
ApplicationPair(boost::function<T()> func, Args... arguments )
{
_func = func(Args::arguments...);
}
ApplicationPair() = delete;
void run();
boost::function<T(Args...)> _func;
};
#endif
And then, what I'd like to do is the following:
main.cpp
template<typename T, typename... Args>
void ApplicationPair<T,Args...>::run()
{
this->_func;
}
//TEST
int counter = 0;
void HelloWorld()
{
std::cout << "HelloWorld\n";
}
void printNumber(int i)
{
std::cout << "Print: " << i << std::endl;
}
void increaseCounter(int x)
{
counter+=x;
}
int main()
{
ApplicationPair<void> p1(HelloWorld);
ApplicationPair<void> p2(printNumber, 5);
ApplicationPair<void> p3(increaseCounter, 10);
p1.run();
p2.run();
p3.run();
return 0;
}
Basically, the methods I want to store shouldn't be modified or adapted in any way: I want to be able to create any kind of method without caring about the fact that struct ApplicationPair will store it for its own personal use.
All I get with this though is a long string of errors like:
error: in declaration ‘typename boost::enable_if_c<(! boost::is_integral::value), boost::function&>::type boost::function::operator=(Functor)’
In the below line:
ApplicationPair<void> p2(printNumber, 5);
you have to specify all types in template arguments list, not only void as return type, int as argument of constructor should also be added. Now args... is empty. What is wrong. The same with p3.
Make constructor as templated method taking paramters pack as argument for your callable:
template<class F, class ... Args>
ApplicationPair(F&& func, Args... arguments )
{
_func = boost::bind(std::forward<F>(func),arguments...);
}
then args... can be deduced when invoking constructor. Your class template takes only a type for return value.
template<class Ret>
struct ApplicationPair {
template<class F, class ... Args>
ApplicationPair(F&& func, Args... arguments )
{
_func = boost::bind(std::forward<F>(func),arguments...);
}
ApplicationPair() = delete;
void run() {
this->_func();
}
boost::function<Ret()> _func;
};
In constructor boost::bind is used to bind passed parameters to callable. You don't store parameters anywhere, therefore they must be bound in functor created by boost::bind.
Uses:
ApplicationPair<void> p1(HelloWorld);
ApplicationPair<void> p2(printNumber, 5);
ApplicationPair<void> p3(increaseCounter, 10);
Demo
Don't use boost::bind, it is limited to handle only max 9 arguments.
You've already gotten an answer but here's a C++17 alternative capable of deducing the return value type as well as the argument types of the function using a deduction guide, making both the return type and argument types part of the ApplicationPair<> type. I've chosen to store the arguments separately in a std::tuple<Args...>.
boost::function can be replaced with std::function in this example in case you later decide to go with the standard:
#include <boost/function.hpp>
#include <iostream>
#include <type_traits>
#include <tuple>
template<typename T, typename... Args>
struct ApplicationPair {
ApplicationPair() = delete;
ApplicationPair(Func func, Args... args) :
_func(func),
// store the arguments for later use
arguments(std::make_tuple(std::forward<Args>(args)...))
{}
decltype(auto) run() { // I'd rename this: decltype(auto) operator()()
return std::apply(_func, arguments);
}
boost::function<T(Args...)> _func;
std::tuple<Args...> arguments;
};
// deduction guide
template<typename Func, typename... Args>
ApplicationPair(Func, Args...) ->
ApplicationPair<std::invoke_result_t<Func, Args...>, Args...>;
int counter = 0;
void HelloWorld()
{
std::cout << "HelloWorld\n";
}
void printNumber(int i)
{
std::cout << "Print: " << i << std::endl;
}
int increaseCounter(int x) // changed return type for demo
{
counter+=x;
return counter;
}
int main()
{
// full deduction using the deduction guide
ApplicationPair p1(HelloWorld);
ApplicationPair p2(printNumber, 5);
ApplicationPair p3(increaseCounter, 10);
p1.run();
p2.run();
std::cout << p3.run() << '\n';
std::cout << p3.run() << '\n';
}
I have the following template function:
template<class T, class F> T function(F& f) {
...
T t;
f(t);
return t;
}
It's expected to be used with F with the form
void some_function(SomeType& s);
in this way
function<SomeType>(some_function);
The first template argument seems redundant because can be deduced from the parameters of the parameter function.
The question is
Exists a way to get rid of the first template parameter?
Something like
template<class F> first_param_type<F> function(F& f) {
...
first_param_type<F> t;
f(t);
return t;
}
So that I can use it as
function(some_function);
template<class T>
T function( void(*f)(T&) ) {
...
T t;
f(t);
return t;
}
solves the problem as stated. The general problem cannot be solved (where F is an arbitrary callable), as callables in C++ can accept more than one type, and deducing what types are acceptable cannot be solved in the general case.
If you had a list of types you support, it an be solved in general.
The basic problem in C++14 is function([](auto&x){ std::cout << x << '\n'; }). The same problem exists in C++11 with function objects with a template operator(). The fact that auto-lambdas are supported in C++14 means that such objects are going to become more and more common in the future.
Consider changing your design so that the signature of your F is T() rather than void(T&). Then we get:
template<class F>
std::result_of_t<F()>
function( F&& f ) {
...
return std::forward<F>(f)();
}
or typename std::result_of<F()>::type in C++11.
I hope I understood your question, maybe I am wrong...
First of all I expect your template function must be called and for the call it needs additional parameters which I could not found in your example code.
But ok, what I expect what you can do:
#include <iostream>
using namespace std;
template <typename RetType, typename ... Parms>
auto TemplateFunction ( RetType(*ptr)(Parms ...), Parms ... parms ) -> RetType
{
RetType ret;
ret = (*ptr)( parms...);
cout << "Value ret in Wrapper is:" << ret << endl;
return ret;
}
double AnyFunc(int a, int b) { return 3.14 * a + b; }
std::string OtherFunc( ) { return "Hallo"; }
int main()
{
double result = TemplateFunction(&AnyFunc, 1,3);
cout << "Result is " << result << endl;
cout << TemplateFunction(&OtherFunc) << endl;
}
As you already mentioned, there is no need to give the return type as additional parameter, because it can be found in the given as type in the presented function pointer to the template.
The wrapper template will work for all return types but not for void!
UPDATE
I absolutely agree with Yakk's answer I just wanted to mention an other but very similar way:
#include <functional>
template < class Type >
Type myFunction( const std::function< void( Type& ) >& aFunction )
{
Type instance;
aFunction( instance );
return instance;
}
I have the following code:
#include <functional>
//...
typedef int (*Myfun)(int);
std::function<int (int)> fn0([](int a)->int {
return -a;
});
std::cout << "val == " << fn0(3) << std::endl; //"val == -3"
Myfun *fptr = fn0.target<Myfun>(); //fptr is NULL!!
std::cout << "val == " << (*fptr)(3) << std::endl; //Access violation error
Actually, this code is a code from MSDN with a slight change: using lambda instead of a plain function.
Why does the call fn0.target<Myfun>() returns NULL?
When I declare a regular function
int neg(int val) {
return (-val);
}
and write std::function<int (int)> fn0(neg);, everything seems to work, but lambda is not been handled correctly.
The type Myfun from typedef int (*Myfun)(int); is not related to the type of the function's target, which is the unique, unnamed type of the closure object produced by executing the expression [](int a)->int { return -a; }
Try executing std::cout << fn0.target_type().name() << '\n'; to see for yourself.
When you declare a function with int neg(int val) { return (-val); }, the type of neg is exactly Myfun (after function-to-pointer conversion, which happens in std::function<int(int)> fn0(neg)), which is why std::function::target() is able to return a pointer to it.
Cubbi explained why your code doesn't work -- a lambda is not a function pointer.
Now, trivial lambdas can be converted to function pointers. So supposed you really want to force that conversion?
template<typename F>
struct as_pointer_t {
F f;
template<typename R, typename... Args>
operator type<R(*)(Args...)>() const { return {f}; }
template<typename R, typename... Args>
operator std::function<R(Args...)>() const { return (R(*)(Args...))f; }
};
template<typename F>
as_pointer_t<F> as_pointer( F&& f ) { return {std::forward<F>(f)}; }
now we can do this:
int main() {
typedef int (*Myfun)(int);
std::function<int (int)> fn0(as_pointer([](int a)->int {
return -a;
}));
std::cout << "val == " << fn0(3) << std::endl; //"val == -3"
Myfun *fptr = fn0.target<Myfun>(); //fptr is no longer NULL!!
std::cout << "val == " << (*fptr)(3) << std::endl;
}
and your code works as expected. However, the above only compiles if your lambda captures nothing.
If your goal is to convert a capturing lambda to a function pointer, you cannot. You can store the state in a global variable, and use it in a non-capturing lambda. You can also convert a capturing lambda into a function-pointer and void* pair.
I have written code that takes a compile-time index to inject the void* into the list (and an optional type to use instead of void*), and produces said pair of void* and function pointer. The general case is tricky -- the specific case (say, the first argument) is far easier.
template<typename T> using type=T;
template<typename F, typename X=void*>
struct callback_t {
F f;
operator X() { return X(&f); }
template<typename R, typename...Args>
operator type<R(*)(X, Args...)>() const {
return []( X x, Args... args )->R {
F* f = (F*)(x);
return (*f)(std::forward<Args>(args)...);
};
}
};
template<typename X=void*, typename F>
callback_t<F,X> make_callback( F f ) {
return {std::forward<F>(f)};
}
use:
typedef void(*pfun)(void*, int);
void call_pfun( pfun f, void* p) {
for (int i = 0; i < 3; ++i)
f( p, i );
}
int main()
{
int y = 7;
auto callback = make_callback([y]( int x ) { std::cout << x+y << "\n"; });
call_pfun( callback, callback );
}
live example.
I'm trying to implement simple ScopedExit class. Here's the code:
#include <iostream>
#include <functional>
template<class R, class... Args>
class ScopedExit
{
public:
ScopedExit(std::function<R(Args...)> exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<R(Args...)> exitFunc_;
};
template<>
class ScopedExit<void>
{
public:
ScopedExit(std::function<void ()> exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<void ()> exitFunc_;
};
void foo()
{
std::cout << "foo() called\n";
}
class Bar
{
public:
void BarExitFunc(int x, int y)
{
std::cout << "BarExitFunc called with x =" << x << "y = " << y << "\n";
}
};
int main()
{
Bar b;
std::cout << "Register scoped exit func\n";
{
ScopedExit<void, int, int> exitGuardInner(std::bind(&Bar::BarExitFunc, &b, 18, 11));
}
ScopedExit exitGuardOutter(foo);
std::cout << "About to exit from the scope\n";
return 0;
}
So, there are a couple of questions:
How to pass exit's function arguments to it? For example, I bind BarExitFunc with two integer arguments: 18 and 11. So how can I pass it to the exitFunc_ in the destructor? I think I need something like invoke function with std::forward<>.
gcc 4.7.2 (from ideone.com) complains about exitGuardOutter. It says:
prog.cpp:60:16: error: missing template arguments before ‘exitGuardOutter’
prog.cpp:60:16: error: expected ‘;’ before ‘exitGuardOutter’
Thanks in advance.
How to pass exit's function arguments to it? For example, I bind BarExitFunc with two integer arguments: 18 and 11. So how can I pass it to the exitFunc_ in the destructor?
I can see no reason whatsoever to pass arguments to exitFunc_ at call time in the destructor. Whatever you do, you'll have to provide those arguments upfront in the ScopedExit constructor anyway.
The most straightforward way is simply to use a function<R()> and bind any required arguments at the definition site like you're already doing:
ScopedExit<R> guard(std::bind(someFunction, someArg, otherArg));
This allows you to get rid of the variadic template arguments altogether and simplifies your template a lot.
Now, if what is bothering you is that you have to type std::bind and you would rather use such a syntax:
ScopedExit<R> guard(someFunction, someArg, otherArg);
Really, I don't see the point since it makes the template more complicated, but why not... Just bind/forward the arguments in the constructor itself and still store a function<R()>:
template<typename... Args>
ScopedExit(std::function<R(Args...)> exitFunction, Args&&... args)
{
exitFunc_ = std::bind(exitFunction, std::forward<Args>(args)...);
}
Now you systematically bind the function even if there are no arguments to bind, so you may want to specialize your class to avoid this useless bind when there are no arguments. This is left as an exercise.
gcc 4.7.2 (from ideone.com) complains about exitGuardOutter
This is because foo isn't a std::function and the compiler can't deduce the correct template arguments. As already mentioned by #ForEveR you could just define your guard variable as ScopedExit<void> guard(foo);.
Or, wrapping it all up and keeping in mind what I first said (bind is best left out of your template and used at the definition site of your guard) you could just get rid of std::function in the constructor and generalize for any functor (which, BTW, is how the Standard library does whenever it needs a functor/callback). For storage you can just use std::function<void()> since it accepts non-void return types too:
class ScopedExit
{
public:
template<typename Functor>
ScopedExit(Functor exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<void()> exitFunc_;
};
int foo() { return 0; }
struct Bar {
void bye(int, int) {}
};
struct Baz {
void operator ()() {}
};
int main() {
const std::string what = "lambda!";
ScopedExit guard1([&]() { std::cout << "yay a " << what << std::endl; });
ScopedExit guard2(foo); // note how std::function<void()> accepts non-void return types
Bar b;
ScopedExit guard3(std::bind(&Bar::bye, &b, 1, 2));
ScopedExit guard4(Baz());
}
Note how your original variadic template class has now become a flexible non-template class with just a templated constructor whose template argument is deduced automatically, and which accepts almost[see note below] any kind of functor you can think about.
Note: I said almost any functor because this doesn't work with default arguments:
void foobar(int = 0) {}
ScopedExit guard5(foobar); // error: too few arguments to function
Even if you stored a Functor directly instead of a std::function<void()> you wouldn't be able to make use of the default arguments anyway (the signature of foobar is still void(int) even with a default argument) so one always has to handle this corner-case at the definition site with something like:
void foobar(int = 0) {}
ScopedExit guard5([]() { foobar(); });
1) You can save arguments in tuple for example. However, in your case, you can simply call exitFunc_() and function definition should be std::function<R()> exitFunction since you already bind arguments to function. Something like this probably
#include <iostream>
#include <functional>
#include <tuple>
template<size_t...>
struct indices {};
template<size_t N, size_t... Is>
struct gen_indices : gen_indices<N - 1, N - 1, Is...>
{
};
template<size_t... Is>
struct gen_indices<0, Is...> : indices<Is...>
{
};
template<class R, class... Args>
class ScopedExit
{
public:
ScopedExit(std::function<R(Args...)> exitFunction, Args&&... args)
: arguments_(std::forward_as_tuple(args...))
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
call(gen_indices<sizeof...(Args)>());
}
private:
template<size_t... Idx>
void call(indices<Idx...>)
{
exitFunc_(std::forward<Args>(std::get<Idx>(arguments_))...);
}
std::tuple<Args...> arguments_;
std::function<R(Args...)> exitFunc_;
};
template<>
class ScopedExit<void>
{
public:
ScopedExit(std::function<void ()> exitFunction)
{
exitFunc_ = exitFunction;
}
~ScopedExit()
{
exitFunc_();
}
private:
std::function<void ()> exitFunc_;
};
void foo()
{
std::cout << "foo() called\n";
}
class Bar
{
public:
void BarExitFunc(int x, int y)
{
std::cout << "BarExitFunc called with x =" << x << "y = " << y << "\n";
}
};
int main()
{
Bar b;
std::cout << "Register scoped exit func\n";
{
ScopedExit<void, int, int> exitGuardInner
(
std::bind(&Bar::BarExitFunc, &b, std::placeholders::_1,
std::placeholders::_2), 10, 18
);
}
ScopedExit<void> exitGuardOutter(foo);
std::cout << "About to exit from the scope\n";
return 0;
}
2) Should be created like ScopedExit<void>.