Can you use templates (or the like) in C++ to specify which operation is done in a function?
I don't know how to explain it more clearly, so I'll show you how it could be (but isn't) done in code:
template <operator OPERATION> int getMaxOrMin(int a, int b) {
return a OPERATION b ? a : b;
}
where finding the maximum or the minimum of a or b would be (this is where my pseudo-syntax gets a little confusing, bear with me):
int max = getMaxOrMin< > > (a, b);
int min = getMaxOrMin< < > (a, b);
I know that's not how to do it at all (because it doesn't even syntactically make sense), but I hope that clarifies the type of thing I want to do.
The reason behind me wondering this is I'm making a PriorityQueue implementation, and it would be nice to easily switch between the backing being a max-heap or a min-heap on the fly without copying and pasting code to make two different classes.
I know I could do it with a macro, but the only way I'd know how to do that would give me either a max-heap or a min-heap, but not both in the same compilation. I'm probably overlooking a way, though.
Do what std::map and friends do: Take a comparison function/functor as your template parameter. See std::less and std::greater.
Do remember that the standard library already has a well developed and debugged priority queue that you can use with an arbitrary comparison function.
Yes but you need to define it like a functor:
template <typename OPERATION>
int getMaxOrMin(int a, int b)
{
OPERATION operation;
return operation(a, b) ? a : b;
}
Now you can use it like this:
struct myLess
{
bool operator()(int a,int b) const { return a < b; }
}
struct myGreat
{
bool operator()(int a,int b) const { return a > b; }
}
void code()
{
int x = getMaxOrMin<myLess>(5,6);
int y = getMaxOrMin<myGreat>(5,6);
}
That seems like a lot of work. But there are a lot of predefined functors in the standard. On this page scroll down to "6: Function Objects".
For your situation there is:
std::less
std::greater
So the code becomes:
template <typename OPERATION>
int getMaxOrMin(int a, int b)
{
OPERATION operation;
return operation(a, b) ? a : b;
}
void codeTry2()
{
int x = getMaxOrMin<std::less<int> >(5,6);
int y = getMaxOrMin<std::greater<int> >(5,6);
}
Related
What I really want to do is to compare the performance of different algorithms which solve the same task in different ways. Such algorithms, in my example called apply_10_times have sub algorithms, which shall be switchable, and also receive template arguments. They are called apply_x and apply_y in my example and get int SOMETHING as template argument.
I think the solution would be to specify a template function as template parameter to another template function. Something like this, where template_function is of course pseudo-code:
template<int SOMETHING>
inline void apply_x(int &a, int &b) {
// ...
}
template<int SOMETHING>
inline void apply_y(int &a, int &b) {
// ...
}
template<template_function APPLY_FUNCTION, int SOMETHING>
void apply_10_times(int &a, int &b) {
for (int i = 0; i < 10; i++) {
cout << SOMETHING; // SOMETHING gets used here directly as well
APPLY_FUNCTION<SOMETHING>(a, b);
}
}
int main() {
int a = 4;
int b = 7;
apply_10_times<apply_x, 17>(a, b);
apply_10_times<apply_y, 19>(a, b);
apply_10_times<apply_x, 3>(a, b);
apply_10_times<apply_y, 2>(a, b);
return 0;
}
I've read that it's not possible to pass a template function as a template parameter, so I can't pass APPLY_FUNCTION this way. The solution, afaik, is to use a wrapping struct, which is then called a functor, and pass the functor as a template argument. Here is what I got with this approach:
template<int SOMETHING>
struct apply_x_functor {
static inline void apply(int &a, int &b) {
// ...
}
};
template<int SOMETHING>
struct apply_y_functor {
static inline void apply(int &a, int &b) {
// ...
}
};
template<typename APPLY_FUNCTOR, int SOMETHING>
void apply_10_times(int &a, int &b) {
for (int i = 0; i < 10; i++) {
cout << SOMETHING; // SOMETHING gets used here directly as well
APPLY_FUNCTOR:: template apply<SOMETHING>(a, b);
}
}
This approach apparently works. However, the line APPLY_FUNCTOR:: template apply<SOMETHING>(a, b); looks rather ugly to me. I'd prefer to use something like APPLY_FUNCTOR<SOMETHING>(a, b); and in fact this seems possible by overloading the operator(), but I couldn't get this to work. Is it possible and if so, how?
As it is not clear why you need APPLY_FUNCTION and SOMETHING as separate template arguments, or why you need them as template arguments at all, I'll state the obvious solution, which maybe isn't applicable to your real case, but to the code in the question it is.
#include <iostream>
template<int SOMETHING>
inline void apply_x(int a, int b) {
std::cout << a << " " << b;
}
template<int SOMETHING>
inline void apply_y(int a, int b) {
std::cout << a << " " << b;
}
template<typename F>
void apply_10_times(int a, int b,F f) {
for (int i = 0; i < 10; i++) {
f(a, b);
}
}
int main() {
int a = 4;
int b = 7;
apply_10_times(a, b,apply_x<17>);
apply_10_times(a, b,apply_y<24>);
}
If you want to keep the function to be called as template argument you can use a function pointer as non-type template argument:
template<void(*F)(int,int)>
void apply_10_times(int a, int b) {
for (int i = 0; i < 10; i++) {
F(a, b);
}
}
int main() {
int a = 4;
int b = 7;
apply_10_times<apply_x<17>>(a, b);
apply_10_times<apply_y<24>>(a, b);
}
In any case I see no reason to have APPLY_FUNCTION and SOMETHING as separate template arguments. The only gain is more complex syntax which is exactly what you want to avoid. If you do need to infer SOMETHING from an instantiation of either apply_x or apply_y, this is also doable without passing the template and its argument separately, though again you'd need to use class templates rather than function templates.
PS:
Ah, now I understand what you mean. Yes, apply_10_times() also uses SOMETHING directly. Sorry, I simplified the code in the question too much.
As mentioned above. This does still not imply that you need to pass them separately. You can deduce SOMETHING from a apply_x<SOMETHING> via partial template specialization. This however requires to use class templates not function templates:
#include <iostream>
template <int SOMETHING>
struct foo {};
template <int X>
struct bar {};
template <typename T>
struct SOMETHING;
template <template <int> class T,int V>
struct SOMETHING<T<V>> { static constexpr int value = V; };
int main() {
std::cout << SOMETHING< foo<42>>::value;
std::cout << SOMETHING< bar<42>>::value;
}
What I really want to do is to compare the performance of different
algorithms which solve the same task in different ways.
You should provide more details about that.
Your first step should be get familiar with Google Benchmark. There is as site which provides it online. This tool give proper patterns for your scenario.
In next step you must be aware that in C and C++ there is "as if rule" which allows optimizer do do wonderful things, but makes creation of good performance test extremely difficult. It is easy write test which doesn't measure actual production code.
Here is cppcon talk showing how many traps are hidden when doing a good performance test fro C++ code. So be very very careful.
Excuse any mistakes in my code, I'm still learning C++ syntax. My question is not about whether the code is correct but whether a literal expression will be optimized away.
Let's say I have a function generated from a non-type template like this:
template <bool add>
int addIt(int a, int b) {
if (add) {
return a + b;
} else {
return a - b;
}
}
int v = addIt<true>(10, 5);
From my understanding, the compiler should expand the template to:
int addIt_someID(int a, int b) {
if (true) {
return a + b;
} else {
return a - b;
}
}
int v = addIt_someID(10, 5);
But since it now says if (true) it should be able to remove that entire branch, resulting in this:
void addIt_someID(int a, int b) {
return a + b;
}
int v = addIt_someID(10, 5);
This should be standard compiler behavior... but is this behavior well enough established that I can be certain of it from all major compilers?
I'm relying upon this behavior for a transpiler, and if it's not guaranteed I will have to implement it myself... if it is guaranteed I can let the C++ compiler to do it and that will save me a lot of time in having to parse and evaluate this myself.
This is never guaranteed for regular if (although I would say chaneces are pretty high). There are two ways to be sure. Simpler one requires C++17 (btw addIt seems to return wrong type):
template <bool add>
int addIt(int a, int b) {
if constexpr (add) {
return a + b;
} else {
return a - b;
}
}
int v = addIt<true>(10, 5);
if constexpr guerantees that this will be evaluated in compile time.
Another option is using template metaprogramming/explicit template specialization. For your code this would be pretty simple:
template <bool add>
int addIt(int a, int b);
template<> int addIt<true>(int a, int b) { return a + b; }
template<> int addIt<false>(int a, int b) { return a - b; }
int v = addIt<true>(10, 5);
For other cases you would need some more work like using std::enable_if and stuff like this
Some background on what I try to do:
I am trying to implement a library doing quantum mechanics. As quantum mechanics is basically just linear algebra, I'm using the armadillo linear algebra library underneath. Armadillo uses lazy evaluation to do some smart tricks with matrices, which gives a pretty good abstraction from what is actually going on and looks close to matlab code.
I want to do something similar, but I also want to be able to use auto, which is not possible with armadillo (or eigen).
I have been looking around a little, and this answer contains what I think is the typical way of implementing this: https://stackoverflow.com/a/414260/6306265
The problem with this approach is that when you write
auto C = A+B;
you get a C that is a matrix_add, not a matrix. Even if matrix_add behaves similarly enough to matrix, the fact that matrix_add contains references to A and B makes it awkward to carry around. E.g.
auto A = matrix(2,2,{0,1,0,1});
auto B = matrix(2,2,{1,0,1,0});
auto C = A+B;
C.printmatrix(); // 1,1 ; 1,1
but
auto A = matrix(2,2,{0,1,0,1});
auto B = matrix(2,2,{1,0,1,0});
auto C = A+B;
A(0,0) = 1;
C.printmatrix(); // 2,1 ; 1,1
which is counter-intuitive. As mathematically intuitive behaviour is what I want to achieve, that is a problem.
Even worse is when I do
auto sumMatrices(const matrix& A, const matrix& B)
{
return A+B;
}
which returns a matrix_add with references to local memory.
I would really like to be able to have the nice, overloaded behaviour but also be able to use auto. My idea was to make a wrapper that can hold either a reference or an instance:
template<class T>
class maybe_reference
{
public:
maybe_reference(const T& t):
ptr_(std::make_unique<T>(t)),
t_(*ptr_)
{}
maybe_reference(std::reference_wrapper<const T> t):
t_(t.get())
{}
const T& get(){return t_;}
private:
unique_ptr<T> ptr_;
const T& t_;
}
It may not be implemented exactly this way, but the general idea is to have two constructors that can be clearly distinguished to ensure that get() returns either the referenced object or the one in the unique_ptr.
Modified matrix_add:
class matrix_add {
public:
friend matrix_add operator+(const matrix& A, const matrix& B);
matrix_add(matrix_add&& other): A_(other.A_.get()), B_(other.B_.get()){}
private:
matrix_add(const matrix& A, const matrix& B): A_(std::ref(A)), B_(std::ref(B)){}
maybe_reference<matrix> A_;
maybe_reference<matrix> B_;
};
I have left out all the parts that make matrix_add behave like a matrix. The idea is to have the object refer to the outside objects A&B as long as it was constructed with A+B, but when it is move-constructed, it would own copies.
My question is basically: does this work?
I have been thinking that the move-constructor may be elided in some or all cases, which might be devastating.
Also, is there an alternative to achieve the same thing? I have been looking, but it seems that for linear algebra at least its either lazy or auto.
EDIT: Thanks to being reminded of the term "expression templates", my google search was a lot more fruitful. I found this reddit-post: https://www.reddit.com/r/cpp/comments/4puabu/news_about_operator_auto/
and the referenced papers, which allow specification of "casts" to auto. That would be the feature that really would make all of this work.
I think, your basic problem is, that lazy evaluation does not mix well with changing state. I see two possible routes out of this:
Make your matrices immutable. If you "modify" a matrix, you actually create a copy with the incorporated change, the original remains intact. This works well semantically (any math works exactly as you expect it to do), however it may incur an intolerable runtime overhead if you are setting your matrices value by value.
This allows your implementation of matrix_add to silently replace itself with a matrix object when it is evaluated, ensuring that each evaluation is only performed at most once.
Make your functions explicit. Don't create matrix_add objects that act as if they were matrices themselves, but create matrix_function objects that operate on some input matrices to yield some result. This allows you to explicitly perform the evaluation where you see fit, and to reuse the functions that you define. However, this approach will lead to a lot of additional code complexity.
I don't think it's a good idea to try to work around this problem by introducing implicit points of forced evaluation: You'll loose large parts of what can be achieved by lazy evaluation, so why bother in the first place? Just my two cents.
You could write a template function evaluate which by default is a NOP, and then overload as necessary.
#include <utility>
#include <type_traits>
struct matrix {};
struct matrix_add {
matrix operator()() const;
};
matrix_add operator + (matrix const& a, matrix const& b);
template<class T> decltype(auto) evaluate(T&& val) { return std::forward<T>(val); }
matrix evaluate(matrix_add const& lazy) { return lazy(); }
matrix evaluate(matrix_add & lazy) { return lazy(); }
matrix evaluate(matrix_add && lazy) { return lazy(); }
int main()
{
auto a = matrix();
auto b = matrix();
auto c = evaluate(a + b);
auto d = evaluate(1 + 2);
static_assert(std::is_same<decltype(c), matrix>::value, "");
static_assert(std::is_same<decltype(d), int>::value, "");
}
I will define a new operator: eager_eval, like this:
namespace lazy {
template<class T>
void eager_eval(T const volatile&)=delete;
template<class T>
struct expression {
template<class D,
std::enable_if_t<std::is_base_of<expression, std::decay_t<D>>{}, int> =0
>
friend T eager_eval( D&& d ) { return std::forward<D>(d); }
};
}
Whenever you want something to be evaluatable in an eager manner, define eager_eval in its namespace, or derive it from lazy::lazy_expression<target_type>.
So we modify your matrix_add to (A) derive from it with the lazy-produced type you want, and (B) have an operator matrix:
struct matrix_add:
lazy::expression<matrix>
{
matrix_add(matrix const& a, matrix const& b) : a(a), b(b) { }
operator matrix() && { // rvalue ref qualified as it should be.
matrix result;
// Do the addition.
return result;
}
private:
matrix const& a, b;
};
and now, anyone can do:
auto e = eager_eval( a+b );
and ADL finds the right type to eager evaluate the lazy expression to.
live example.
You could, optionally, implement a default eager_eval that returns its argument:
template<class T, class...Ts>
T eager_eval(T&& t, Ts&&...) { return std::forward<T>(t); }
then
using lazy::eager_eval;
auto x = eager_eval( 1+2 );
lets you be agnostic to the type you pass to eager_eval; if it is a type that is aware of being lazy via an eager_eval overload, it converts, and if not it does not convert.
The pack in lazy::eager_eval above is to ensure that it has the lowest priority as an overload.
with c++17 class template argument deduction, you may write
struct matrix_expr_foo {};
struct matrix_expr_bar {};
template< typename L, typename R >
struct matrix_add {
// ...
};
matrix_add<matrix_expr_foo,matrix_expr_bar> operator + (matrix_expr_foo const& a, matrix_expr_bar const& b);
template< typename T >
struct expr {
expr( T const& expr ){
// evaluate expr ( to be stored in an appropriate member )
}
// ...
};
int main()
{
auto a = matrix_expr_foo();
auto b = matrix_expr_bar();
expr c = a + b;
/* different naming ?
auto_ c = a + b;
...
*/
}
where expr is meant to act as an auto for expression templates ...
I have a simple problem but I don't know how to solve it because I have never used functors in C++.
I want to do something like that (it is just an example) :
class MyClass
{
void applyFunction(myFunction); /* WRONG SYNTAX */
double *_x;
unsigned int *_size;
};
void MyClass::applyFunction(myFunction) /* WRONG SYNTAX */
{
for (unsigned int i = 0; i < _size; ++i)
myFunction(_x[i], 10.);
}
class OtherClass
{
void myFunction1(double x, double lim);
void myFunction2(double x, double lim);
std::vector _v;
};
void OtherClass::myFunction1(double x, double lim)
{
_v.clear();
if (x > lim)
_v.push_back(x);
}
void OtherClass::myFunction2(double x, double lim)
{
_v.clear();
if (x < lim)
_v.push_back(x);
}
int main()
{
MyClass myClass;
OtherClass otherClass;
myClass.applyFunction(otherClass.myFunction1); /* WRONG SYNTAX */
std::cout<<otherClass._v.size()<<std::endl;
myClass.applyFunction(otherClass.myFunction2); /* WRONG SYNTAX */
std::cout<<otherClass._v.size()<<std::endl;
return 0;
}
What would be the correct syntax to use functors/std::functions ?
Thank you very much !
I'll take you at your word that you want to use functors for this. Just for grins, I'll also assume you want to do this the "right" way, not just find a syntax that will let it compile (and probably run, perhaps doing what you wanted).
In this case, the standard library already has algorithms to support much of what you're doing (especially in C++11). To copy the data that meets some criteria into a target vector, you have std::copy_if (though that's missing in C++98/03 -- you have to reverse the sense of the comparison and use std::remove_copy_if).
Using this, your code becomes something like this:
template <class T>
class less_than {
T limit;
public:
less_than(T lim) : limit(lim) {}
bool operator()(T const &val) { return val < limit; }
};
std::copy_if(source.begin(),
source.end(),
std::back_inserter(target),
less_than<int>(10));
However, if you have C++11 available, it's probably more convenient to use a lambda instead:
std::copy_if(source.begin(),
source.end(),
std::inserter(target),
[](int v) { return v < 10;});
The lambda is basically just a way of getting the compiler to generate an anonymous functor class for you, so there's not much real difference between the two, but the lambda obviously saves quite a bit of typing.
If you're stuck with C++03, you basically just invert the comparison:
template <class T>
class greater_than {
T limit;
public:
bool operator()(T const &val) {
return val > limit;
}
};
std::remove_copy_if(src.begin(),
src.end(),
std::back_inserter(dst),
greater_than(10));
Alternatively, you could write your own copy_if pretty easily -- it was left out of C++98/03 mostly by oversight, not because it needs anything the language doesn't provide, or anything like that (though as I recall, getting all the border conditions exactly right can be a little tricky).
For what it's worth, I should also note that the standard library does have std::less and std::greater, so the less_than and greater_than functors I've given above aren't really necessary. Unfortunately, they just do the comparison, so to use them as we're doing here, you have to use std::bind1st or std::bind2nd to get them to compare to a constant:
std::remove_copy_if(src.begin(),
src.end(),
std::ostream_iterator<int>(std::cout, "\n"),
std::bind1st(std::less<int>(), 10));
void applyFunction(std::function<void(double, double)>);
// ...
applyFunction(std::bind(&OtherClass::myFunction1, &otherClass));
I want to create std::map in STL, but the comparer depends some dynamic value which is available only at runtime.. How can I make this? For example, I want something looks like std::map<int, int, Comp(value1, value2)>. value1 and value2 are not the compared number here, they are some kind of configuration numbers.
Use a functor class:
#include <map>
class Comp
{
public:
Comp(int x, int y) : x(x), y(y) {}
bool operator() (int a, int b) const { /* Comparison logic goes here */ }
private:
const int x, y;
};
int main()
{
std::map<int,float,Comp> m(Comp(value1,value2));
}
This is like a function, but in the form of a runtime object. This means it can have state, which includes runtime configuration. All you have to do is overload operator(). If you define all the member-function bodies in the class definition (as above), then the compiler will probably inline everything, so there'll be negligible performance overhead.
If you know value1 and value2 at compile-time (i.e. if they are compile-time constants), you could use a function template instead:
template <int x, int y>
bool compare(int a, int b) { /* Comparison logic goes here */ }
int main()
{
std::map<int,float,compare<value1,value2> > m;
}