Parameter to use std::greater or std::less as argument - c++

I would like to make a function with a parameter that accepts either std::greater<int> or std::less<int> as the argument. I'm stuck on the syntax for the parameter, though.
This is the format I tried:
myFunction(int a, int b, bool *comp(int, int)) { … }
…
std::greater<int> bigger;
myFunction(2, 3, bigger);
That doesn't work, though, and I suspect the third parameter is just completely wrong. What should it actually be?
cannot convert std::greater<int> to bool* (*)(int, int)

Functions taking a comparator are usually implemented via templates:
template <typename Comparator>
myFunction(int a, int b, Comparator comp) { … }
but you could also use std::function to implement it:
myFunction(int a, int b, std::function<bool (int, int)> ) { … }
The first version exposes code in the header but will usually perform better.
As for the second version, you can hide the implementation in the .cpp file,
but you would lose some performance due to the impossibility to inline the
comparator calls.

So the trick here is that std::less and std::greater are actually stateless function objects that can be trivially constructed. But they don't support casting to a function pointer.
The efficient choices are either (A) take the comparator via template argument and implement the code in a header:
template<typename C> void myFunc( int a, int b, C comp )
which means you have to implement it in a header file, or (B) type erase the function object via a std::function< bool(int, int) >:
void myFunc( int a, int b, std::function< bool(int, int) > comp )
which has some costs (maybe significant? Profile!) (heap allocation is avoided via small object optimization for stateless std less/greater, but it tends to cost a virtual function call regardless, which can also block inlining).
Or (C) write some code that lets you take a stateless functor and turn it into a function pointer:
template<typename T>
using Type = T;
template<typename StatelessFunctor>
struct function_ptr_of_stateless_t {
template<typename R, typename... Args>
operator Type<R(Args...)>*() const {
return [](Args... args)->R {
return StatelessFunctor()(std::forward<Args>(args)...);
};
}
};
template<typename StatelessFunctor>
function_ptr_of_stateless_t<StatelessFunctor> as_function_ptr() {
return {};
}
bool myFunction( int a, int b, bool(*comp)(int, int) ) { return comp(a,b); }
int main() {
std::cout << myFunction(3,7, as_function_ptr<std::less<int>>() ) << "\n";
}
where the template function as_function_ptr takes the type of your stateless functor and creates a throw away type that lets you cast it to any compatible function pointer type.
This has modestly less overhead than the std::function solution, as a call over a function pointer tends to be faster than over a virtual method, and in addition some compilers (like gcc) are quite decent at inlining function pointers, even from one compilation unit to another.
As a bonus, in C++14 you could use:
int main() {
std::cout << myFunction(3,7, as_function_ptr<std::less<>>() ) << "\n";
}
and it still works pretty optimally.

Use a template:
template<class Callable>
myFunction(int a, int b, Callable f);

Related

Can a std::function typedef be used to help define a lambda?

Let's say a I have a typedef for a specific std::function such as:
typedef std::function<int(int a, int b, int c)> func_type;
Can I reuse that typedef when defining a lambda that implements it?
For example, in the example below, the function foo accepts a func_type, but the call-site for foo needs to replicate the signature:
void foo(func_type f) {
// ...
}
int main() {
foo([](int a, int b, int c){ return a + b + c; });
}
Can I somehow re-use the func_type typedef when declaring the lambda, so I don't have to repeat the argument list (and so changes to the func_type typedef will be transparent for lambda bodies that work with the new definition).
Something like [](??? func_type ???){ return a + b + c; }.
The variable names in std::function<int(int a, int b, int c)> are not part of the type -- they are basically comments. There is no way to extract them at any other point.
So if you hope to get a, b and c you are out of luck.
One simple thing you can do is use auto:
foo( [](auto...args) { return args+...+0; } );
which is close to what you want. If you have 3 arguments you can do:
foo( [](auto a, auto b, auto c) { return a+b+c; } );
But the return type doesn't match, other than because std::function does the conversion for you.
You can extract the types of a b and c and make the lambda work differently, but not with the return type. Not unless you do something insane like:
template<class T>
struct tag_t{ contexpr tag_t(){} using type=T; };
template<class T>
constexprt tag_t<T> tag{};
template<class Tag>
using type_t = typename Tag::type;
template<class F>
struct deducer {
F f;
template<class R, class...Args>
operator std::function<R(Args...)>() const {
return f( tag<R>, tag<Args>... );
}
};
template<class F>
deducer<F> make_deducer( F f ){ return {std::move(f)}; }
int main() {
foo(make_deducer([](auto R, auto...Args){
return []( type_t<decltype(Args)>... args )->type_t<decltype(R)> {
return 0+...args;
});
}));
}
I would advise against this. But I deduced the argument types and return type of the lambda from what std::function I was passed to.
What we do here is we create a deducer type, that when converted to a std::function passes the arguments and return type expected to a lambda it stores. That lambda then generates a custom lambda for those exact arguments.
This is neither brief, simple nor sane.
If you know you have a std::function and what you want to do is defer the selection of the type arguments to std::function, you can just have a generic lambda:
foo([](auto... xs) { return (... + xs); });
Since it's std::function's call operator that drives how the lambda is called, this'll do the right thing. Of course, this requires C++14 (and the fold-expression I used above requires C++17, but that's not as important). You may or may not want to use auto&&, depending on what the types actually are.
For C++11, you can't easily do such a thing with a lambda. You'd need to fix the arity and manually list all the types. This isn't practical. You could fallback to using a normal function object, with a call operator template, but then you lose the advantages of a lambda.
A std::function is
is a general-purpose polymorphic function wrapper. Instances of
std::function can store, copy, and invoke any Callable target --
functions, lambda expressions, bind expressions, or other function
objects, as well as pointers to member functions and pointers to data
members. -- source cppreference.com
So yes, this approach is perfectly valid !
However the signature of the typedef can't be taken over to short-circuit the lambda definition.
Remark: The typedef is about the return type and the parameter types but not the parameter names, so if short-circuiting the parameter list would be legal, the body of the lambda would not know which parameters to use:
int main() {
foo([](int d, int e, int f){ return d + e + f; });
}

Cast function type to differ if types of arguments are convertable

I am writing a wrapper class for callable types (pointer to function, functors, etc). I want to implement something like std::function.
I define constructor from pointer to function:
template <typename Ret, typename... Args>
class function<Ret(Args...)>
{
public:
function(Ret (func)(Args...))
{
m_fn_ptr = func;
}
}
Now, let's assume that i want to use my class like this:
int int_function(int n)
{
return n;
}
function<int(short)> wrapper(&int_function); // compile error
Despite that short are implicit convertable to int compiler cannot deduce template parameters and call appropriate constructor.
Then i tried this:
template <typename FRet, typename... FArgs>
function(FRet (func)(FArgs...))
{
m_fn_ptr = static_cast<Ret (*f)(Args...)>(func);
}
But I got invalid static cast.
How can I fix that ?
The super_func is a function object with no state that can convert to any compatible call signature.
template<class T>using type=T;
template<class Sig, Sig* func>
struct super_func;
template<class R, class...Args, R(*func)(Args...)>
struct super_func<R(Args...), func> {
using Sig = R(Args...);
using pSig = Sig*;
template<class R2, class...Args2, std::enable_if_t<
std::is_convertible<
std::result_of_t<pSig(Args2...)>,
R2
>{}
&& !std::is_same<R2, void>{},
bool
> =true>
constexpr operator type<R2(Args2...)>*() const {
return [](Args2...args)->R2{
return func(std::forward<Args2>(args)...);
};
}
template<class...Args2, std::enable_if_t<
std::is_same<
std::result_of_t<pSig(Args2...)>,
R
>{},
bool
> =true>
constexpr operator type<void(Args2...)>*() const {
return [](Args2...args)->void{
func(std::forward<Args2>(args)...);
};
}
constexpr operator pSig() const {
return func;
}
constexpr R operator()(Args...args)const{
return func(std::forward<Args>(args)...);
}
};
live example. A super_func is stateless. To use it on a function foo, do:
super_func< decltype(foo), &foo > super_foo;
and you get a callable stateless empty object which behaves a lot like foo does, except you can assign it to a pointer to any compatible function pointer and it generates it "on the fly" at compile time.
A super_foo can be fed to your function object.
Doing this on the fly doesn't work without the exterior help, as we need the foo to be a truly static bit of information. By the time it becomes a variable, it is too late to do this statelessly, so we cannot use the lambda trick (without an extra pvoid) to generate a function pointer for the exact signature we want.
You could do a macro:
#define SUPER(X) super_func< decltype(X), &X >{}
and then create your function object with function<double()> f(SUPER(foo));
Another approach is to store an extra pointer's worth of state, and create "the fastest possible delegate" style type erasure. (that term can be googled for one of many implementations, each faster than the last).
How can I fix that ?
Use the correct types when creating wrapper.
Instead of using
function<int(short)> wrapper(&int_function);
use
function<int(int)> wrapper(&int_function);
Remember that class templates instantiated with int and short are very different types and are not convertible to each other.
template <typename T> struct Foo {};
Foo<int> a;
Foo<short> b = a; // Not OK.
Foo<short> c;
Foo<int> d = c; // Not OK.
Your function constructor expects a pointer to a function that takes a short, not an int. The fix is to provide it such a function. The easiest way to do that is to use a lambda with an empty capture-list, that is implicitly convertible to a function pointer:
function<int(short)> wrapper( [](short s) { return int_function(s); } );

How can I pass a lambda (c++11) into a templated function?

I'm playing around with lambda functions in gcc 4.6.2, and would like to implement a templated "map" function like this:
template<typename A, typename B> std::vector<B> map(const std::vector<A>& orig, const std::function<B(A)> f) {
std::vector<B> rv;
rv.resize(orig.size());
std::transform(begin(orig), end(orig), begin(rv), f);
return rv;
}
This doesn't work, because the test code:
int main(int argc, char **argv) {
std::vector<int> list;
list.push_back(10);
list.push_back(20);
list.push_back(50);
std::vector<int> transformed = map(list, [](int x) -> int { return x + 1; });
std::for_each(begin(transformed), end(transformed), [](int x) { printf("-> %d\n", x); });
return 0;
}
gives this error:
test.cpp:49:80: error: no matching function for call to ‘map(std::vector<int>&, main(int, char**)::<lambda(int)>)’
test.cpp:49:80: note: candidate is:
test.cpp:6:49: note: template<class A, class B> std::vector<B> map(const std::vector<A>&, std::function<B(A)>)
If I remove the templating, and use a vector directly, it compiles fine:
std::vector<int> map(const std::vector<int>& orig, const std::function<int(int)> f) {
std::vector<int> rv;
rv.resize(orig.size());
std::transform(begin(orig), end(orig), begin(rv), f);
return rv;
}
so it must be a problem with the way I'm defining the template.
Has anyone run into this before? I know lambdas are incredibly new.
You don't need to use std::function. Just make the predicate parameter a template value. For example,
template<typename A, typename B> std::vector<B> map(const std::vector<A>& orig, B f) {
std::function<> is more useful as a member value type or for defining non-templated code.
The problem is that the compiler can't figure out what to use for B. In order to determine that type it wants to use the function<> you pass in for f, but you don't pass an std::function<> directly. You pass in something you expect to be used to construct a function<>. And in order to do that implicit construction it needs to know the type of argument. So you've got this circular dependency where the type of argument depends on what you pass in, but what gets passed in depends on the type of argument.
You can break this circular dependency by specifying the template parameters, such as map_<int,int>(list, [](int x) -> char { return x + 1; });
(although I see the functor actually returns a char, not an int, so if the type deduction worked for you here you'd be getting back a vector<char> which cannot be converted to a vector<int> when you assign the result to transformed)
However as has been pointed out, generally templates take functors as just a plain template type:
template<typename A,typename Func>
auto map_(const std::vector<A>& orig, Func f) -> std::vector<decltype(f(A()))> {
std::vector<decltype(f(A()))> rv;
/*...*/
}
(we use the trailing return type because we need to use the expression f in the return type, which isn't available unless the return type comes afterwards.)
This allows the template to deduce the functor type directly and avoids any type conversions and best allows for optimization.
It's also customary to use iterators as arguments on these sorts of functions, in which case your function is just a wrapper around std::transform, so you can just use that directly. I'm not sure there's a whole lot of value in a special version that deals with vectors specifically.
I'm tackling with lambdas too and i noticed that you can declare a function pointer in a function definition's parameter list and when you make a call to that function you can pass a lambda expression as an argument if it matches the function prototype of course.
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
template <typename T,typename C>
struct map {
typedef C (*F)(const T&);
std::vector<C> rv;
map () {}
map (const std::vector<T>& o,F f) {
rv.resize(o.size());
std::transform (o.begin(),o.end(),rv.begin(),f);
}
~map () {}
operator std::vector<C> () const {
return rv;
}
};
int main () {
std::vector<int> asd(5,12);
std::vector<char> transformed=map<int,char>(asd,[](const int& x)->char {return x+1;});
std::copy (transformed.begin(),transformed.end(),std::ostream_iterator<int>(std::cout," "));
}

templated operator() overload C++

someone already asked this question, but the thread ended up with the original question not getting answered.
suppose you have this:
template<size_t i, class f_type>
void call_with_i(f_type f);
functor_type is either:
a) a struct with a method that has the following signature:
template<size_t i> operator()() const;
or, b) a function that looks like this:
template<size_t i> foo();
I want "call_with_i<42>(foo)" to be equivalent to "foo<42>()", but I can't figure out the right syntax to make that happen. I'd be satified with a solution that does just (a) but (a)+(b) would be great. I've already tried these syntaxes:
f< i >(); // doesn't work
f()< i >; // doesn't work
f.operator< i >(); // doesn't work
f.operator()< i >; // doesn't work
f.operator()< i >(); // works on msvc, but doesn't work on gcc.
How do you invoke operator() with explicit template arguments? Is there a way to invoke it in a way that the same syntax would also call a templated free function?
p.s. If you're wondering what i'm using this for, its because I'm writing a function repeat_to where repeat_to<10>(f) invokes f(0) then f(1) ... f(10). I'm using this to iterate through multiple boost::fusion vectors in parallel by index. yeah, i could use iterators, or i could just use a named member function, but i still want to know the answer.
edit note: i striked out stuff because passing a templated free function as an arg doesn't make any sense.
The member template is a dependent name, because its semantics depend on the type of f_type. That means you should put "template" before its name (to disambiguate the use of the "less-than" token), similar to how you should put typename before dependent qualified names:
template<size_t i, class f_type>
void call_with_i(f_type f) {
f.template operator()<i>();
// f.template foo<i>();
}
As a workaround, you may use a helper type:
template<size_t N> struct size_t_ { }; // or boost::mpl::int_
template<size_t i, class f_type>
void call_with_i(f_type f) {
f(size_t_<i>());
}
Now, you could define your operator() as follows:
template<size_t i> void operator()(size_t_<i>) const {
// i was deduced automatically by the function argument.
}
This comes handy for templated constructors, for which you cannot do f_type()<i>() or something. They will have to be deducible in that case.
In a case like yours I would use boost::function as functor type. You can then pass both function objects and function pointers while retaining the same interface.
#include <iostream>
template<size_t i, class f_type> void call_with_i(f_type f);
struct A {
template < size_t i >
void operator()() const {
/* no link err in demo */
}
template < size_t i >
void foo() {
/* no link err in demo */
}
};
int main(int argc, char * const argv[]) {
A f;
enum { Constant = 42 };
f.operator()<Constant>();
f.foo<Constant>();
return 0;
}
Is there a way to invoke it in a way that the same syntax would also call a templated free function?
Can you clarify? (pseudocode, or something)

Function passed as template argument

I'm looking for the rules involving passing C++ templates functions as arguments.
This is supported by C++ as shown by an example here:
void add1(int &v) { v += 1 }
void add2(int &v) { v += 2 }
template <void (*T)(int &)>
void doOperation()
{
int temp = 0;
T(temp);
std::cout << "Result is " << temp << std::endl;
}
int main()
{
doOperation<add1>();
doOperation<add2>();
}
Learning about this technique is difficult, however. Googling for "function as a template argument" doesn't lead to much. And the classic C++ Templates The Complete Guide surprisingly also doesn't discuss it (at least not from my search).
The questions I have are whether this is valid C++ (or just some widely supported extension).
Also, is there a way to allow a functor with the same signature to be used interchangeably with explicit functions during this kind of template invocation?
The following does not work in the above program, at least in Visual C++, because the syntax is obviously wrong. It'd be nice to be able to switch out a function for a functor and vice versa, similar to the way you can pass a function pointer or functor to the std::sort algorithm if you want to define a custom comparison operation.
struct add3 {
void operator() (int &v) {v += 3;}
};
...
doOperation<add3>();
Pointers to a web link or two, or a page in the C++ Templates book would be appreciated!
Yes, it is valid.
As for making it work with functors as well, the usual solution is something like this instead:
template <typename F>
void doOperation(F f)
{
int temp = 0;
f(temp);
std::cout << "Result is " << temp << std::endl;
}
which can now be called as either:
doOperation(add2);
doOperation(add3());
See it live
The problem with this is that if it makes it tricky for the compiler to inline the call to add2, since all the compiler knows is that a function pointer type void (*)(int &) is being passed to doOperation. (But add3, being a functor, can be inlined easily. Here, the compiler knows that an object of type add3 is passed to the function, which means that the function to call is add3::operator(), and not just some unknown function pointer.)
Template parameters can be either parameterized by type (typename T) or by value (int X).
The "traditional" C++ way of templating a piece of code is to use a functor - that is, the code is in an object, and the object thus gives the code unique type.
When working with traditional functions, this technique doesn't work well, because a change in type doesn't indicate a specific function - rather it specifies only the signature of many possible functions. So:
template<typename OP>
int do_op(int a, int b, OP op)
{
return op(a,b);
}
int add(int a, int b) { return a + b; }
...
int c = do_op(4,5,add);
Isn't equivalent to the functor case. In this example, do_op is instantiated for all function pointers whose signature is int X (int, int). The compiler would have to be pretty aggressive to fully inline this case. (I wouldn't rule it out though, as compiler optimization has gotten pretty advanced.)
One way to tell that this code doesn't quite do what we want is:
int (* func_ptr)(int, int) = add;
int c = do_op(4,5,func_ptr);
is still legal, and clearly this is not getting inlined. To get full inlining, we need to template by value, so the function is fully available in the template.
typedef int(*binary_int_op)(int, int); // signature for all valid template params
template<binary_int_op op>
int do_op(int a, int b)
{
return op(a,b);
}
int add(int a, int b) { return a + b; }
...
int c = do_op<add>(4,5);
In this case, each instantiated version of do_op is instantiated with a specific function already available. Thus we expect the code for do_op to look a lot like "return a + b". (Lisp programmers, stop your smirking!)
We can also confirm that this is closer to what we want because this:
int (* func_ptr)(int,int) = add;
int c = do_op<func_ptr>(4,5);
will fail to compile. GCC says: "error: 'func_ptr' cannot appear in a constant-expression. In other words, I can't fully expand do_op because you haven't given me enough info at compiler time to know what our op is.
So if the second example is really fully inlining our op, and the first is not, what good is the template? What is it doing? The answer is: type coercion. This riff on the first example will work:
template<typename OP>
int do_op(int a, int b, OP op) { return op(a,b); }
float fadd(float a, float b) { return a+b; }
...
int c = do_op(4,5,fadd);
That example will work! (I am not suggesting it is good C++ but...) What has happened is do_op has been templated around the signatures of the various functions, and each separate instantiation will write different type coercion code. So the instantiated code for do_op with fadd looks something like:
convert a and b from int to float.
call the function ptr op with float a and float b.
convert the result back to int and return it.
By comparison, our by-value case requires an exact match on the function arguments.
Function pointers can be passed as template parameters, and this is part of standard C++
. However in the template they are declared and used as functions rather than pointer-to-function. At template instantiation one passes the address of the function rather than just the name.
For example:
int i;
void add1(int& i) { i += 1; }
template<void op(int&)>
void do_op_fn_ptr_tpl(int& i) { op(i); }
i = 0;
do_op_fn_ptr_tpl<&add1>(i);
If you want to pass a functor type as a template argument:
struct add2_t {
void operator()(int& i) { i += 2; }
};
template<typename op>
void do_op_fntr_tpl(int& i) {
op o;
o(i);
}
i = 0;
do_op_fntr_tpl<add2_t>(i);
Several answers pass a functor instance as an argument:
template<typename op>
void do_op_fntr_arg(int& i, op o) { o(i); }
i = 0;
add2_t add2;
// This has the advantage of looking identical whether
// you pass a functor or a free function:
do_op_fntr_arg(i, add1);
do_op_fntr_arg(i, add2);
The closest you can get to this uniform appearance with a template argument is to define do_op twice- once with a non-type parameter and once with a type parameter.
// non-type (function pointer) template parameter
template<void op(int&)>
void do_op(int& i) { op(i); }
// type (functor class) template parameter
template<typename op>
void do_op(int& i) {
op o;
o(i);
}
i = 0;
do_op<&add1>(i); // still need address-of operator in the function pointer case.
do_op<add2_t>(i);
Honestly, I really expected this not to compile, but it worked for me with gcc-4.8 and Visual Studio 2013.
In your template
template <void (*T)(int &)>
void doOperation()
The parameter T is a non-type template parameter. This means that the behaviour of the template function changes with the value of the parameter (which must be fixed at compile time, which function pointer constants are).
If you want somthing that works with both function objects and function parameters you need a typed template. When you do this, though, you also need to provide an object instance (either function object instance or a function pointer) to the function at run time.
template <class T>
void doOperation(T t)
{
int temp=0;
t(temp);
std::cout << "Result is " << temp << std::endl;
}
There are some minor performance considerations. This new version may be less efficient with function pointer arguments as the particular function pointer is only derefenced and called at run time whereas your function pointer template can be optimized (possibly the function call inlined) based on the particular function pointer used. Function objects can often be very efficiently expanded with the typed template, though as the particular operator() is completely determined by the type of the function object.
The reason your functor example does not work is that you need an instance to invoke the operator().
Came here with the additional requirement, that also parameter/return types should vary.
Following Ben Supnik this would be for some type T
typedef T(*binary_T_op)(T, T);
instead of
typedef int(*binary_int_op)(int, int);
The solution here is to put the function type definition and the function template into a surrounding struct template.
template <typename T> struct BinOp
{
typedef T(*binary_T_op )(T, T); // signature for all valid template params
template<binary_T_op op>
T do_op(T a, T b)
{
return op(a,b);
}
};
double mulDouble(double a, double b)
{
return a * b;
}
BinOp<double> doubleBinOp;
double res = doubleBinOp.do_op<&mulDouble>(4, 5);
Alternatively BinOp could be a class with static method template do_op(...), then called as
double res = BinOp<double>::do_op<&mulDouble>(4, 5);
EDIT
Inspired by comment from 0x2207, here is a functor taking any function with two parameters and convertible values.
struct BinOp
{
template <typename R, typename S, typename T, typename U, typename V> R operator()(R (*binaryOp )(S, T), U u, V v)
{
return binaryOp(u,v);
}
};
double subD(double a, int b)
{
return a-b;
}
int subI(double a, int b)
{
return (int)(a-b);
}
int main()
{
double resD = BinOp()(&subD, 4.03, 3);
int resI = BinOp()(&subI, 4.03, 3);
std::cout << resD << std::endl;
std::cout << resI << std::endl;
return 0;
}
correctly evaluates to double 1.03 and int 1
Edit: Passing the operator as a reference doesnt work. For simplicity, understand it as a function pointer. You just send the pointer, not a reference.
I think you are trying to write something like this.
struct Square
{
double operator()(double number) { return number * number; }
};
template <class Function>
double integrate(Function f, double a, double b, unsigned int intervals)
{
double delta = (b - a) / intervals, sum = 0.0;
while(a < b)
{
sum += f(a) * delta;
a += delta;
}
return sum;
}
.
.
std::cout << "interval : " << i << tab << tab << "intgeration = "
<< integrate(Square(), 0.0, 1.0, 10) << std::endl;