Say I have a binary search function which initializes and uses a lambda:
bool custom_binary_search(std::vector<int> const& search_me)
{
auto comp = [](int const a, int const b)
{
return a < b;
};
return std::binary_search(search_me.begin(), search_me.end(), comp);
}
Without pointing out that this is completely redundant and just focusing on the lambda; is it expensive to be declaring and defining that lambda object every time? Should it be static? What would it mean for a lambda to be static?
The variable 'comp' with type <some anonymous lambda class> can be made static, pretty much as any other local variable, i.e. it is the same variable, pointing to the same memory address, every time this function is run).
However, beware of using closures, which will lead to subtle bugs (pass by value) or runtime errors (pass-by-reference) since the closure objects are also initialized only once:
bool const custom_binary_search(std::vector<int> const& search_me, int search_value, int max)
{
static auto comp_only_initialized_the_first_time = [max](int const a, int const b)
{
return a < b && b < max;
};
auto max2 = max;
static auto comp_error_after_first_time = [&max2](int const a, int const b)
{
return a < b && b < max2;
};
bool incorrectAfterFirstCall = std::binary_search(std::begin(search_me), std::end(search_me), search_value, comp_only_initialized_the_first_time);
bool errorAfterFirstCall = std::binary_search(std::begin(search_me), std::end(search_me), search_value, comp_error_after_first_time);
return false; // does it really matter at this point ?
}
Note that the 'max' parameter is just there to introduce a variable that you might want to capture in your comparator, and the functionality this "custom_binary_search" implements is probably not very useful.
the following code compiles and runs ok in visual studio 2013:
bool const test(int & value)
{
//edit `&value` into `&` #log0
static auto comp = [&](int const a, int const b)
{
return a < (b + value);
};
return comp(2,1);
}
And later:
int q = 1;
cout << test(q); // prints 0 //OK
q++;
cout << test(q); // prints 1 //OK
The compiler will transform any lambda declaration into a regular function and this is done at compile time. The actual definition in the test function is just a regular assignment to the comp variable with the pointer to a c function.
Closures are the generaly the same but will work ok only in the scope they were defined. In any other scope they will fail or generate a memory corruption bug.
Defining comp static would only improve the performance insignificantly or not at all.
Hope this helps:
Razvan.
Related
This is function defintion
template<typename Iter, typename T>
Iter lower_bound(Iter left, Iter right, const T& value){
while (left < right){
auto mid = std::next(left, std::distance(left, right)/2);
if (*mid < value){
left = std::next(mid);
}else{
right = mid;
}
}
return left;
}
template<typename Iter, typename T, typename Predicate>
Iter binary_search2(Iter left, Iter right, const T& value, Predicate funct){
auto it = my::lower_bound(left, right, value);
if (it != right && funct(*it)){
return it;
}else{
return right;
}
}
funct should be something like {return *it == value};
So I figure I would use a lambda function in the main method as follows:
auto searchValue = 10;
int comparisons = 0; // see how many comparison made
auto iter = my::binary_search2(std::begin(data), std::end(data), searchValue, [&comparisons](int& num){
++comparisons;
return num == searchValue;
});
I get a strange error "searchValue' cannot be implicitly captured in a lambda with no capture-default specified"
Any ideas?
Instead of writing [&comparisons] you can write [&] to specify that we want to implicitly capture things by reference by default.
Otherwise you might write it explicitly. [&comparisons, &searchValue]
Because until you do one of those things, the compiler cannot know if you intended capture by value for searchValue. ([=])
Think of a lambda like
auto x = [](int a) -> int {
return a + 2;
};
as something like
struct Lambda {
int operator()(int a) const{
return a + 2;
}
};
Here
x(1) == Lambda{}(1) // == 3
Now, if one wants to capture an extra variable from outside the lambda context as:
int y = 5;
auto x = [y](int a) -> int {
return a + y;
};
That's roughly equivalent to
struct Lambda {
explicit Lambda2(int y): y(y){}
int operator()(int a) const{
return a + y;
}
private:
int y;
};
Hence, now
x(1) == Lambda{y} // == 6
The second case is what is called the Capturing Lambda because, well... it captures variables from outside its scope. One needs to provide the lambda (or the roughly equivalent struct) the list of variables it needs to capture for later use when it shall be invoked.
There are many ways to capture variables. For your question, one approach could be to capture the variable by value since it's a plain integer
auto iter = my::binary_search2(std::begin(data), std::end(data), searchValue,
[&comparisons, searchValue](int& num){
++comparisons;
return num == searchValue;
});
A copy of the variable searchValue is passed. Which is something like how the second Version of struct Lambda used.
Another way would be to capture it by reference in case searchValue was a variable that had an expensive copy or one wanted to modify it in the lambda body. [This is roughly equivalent to passing in a reference to the constructor of struct Lambda]
auto iter = my::binary_search2(std::begin(data), std::end(data), searchValue,
[&comparisons, &searchValue](int& num){
++comparisons;
return num == searchValue;
});
If you want to capture by reference but don't want it to be modified in the lambda body then one can do something like
auto iter = my::binary_search2(std::begin(data), std::end(data), searchValue,
[&comparisons, &constSV = std::as_const(searchValue)](int& num){
++comparisons;
return num == constSV;
});
by using the std::as_const to obtain a const reference to the captured variable. This is equivalent to passing in a const& to the constructor of struct Lambda.
These are some of the capture types that can be used.
I was practicing lambda functions in C++, following code works fine
void insertionSort(int* a, int size, bool reverse=false) {
auto comp = [](int a, int b, bool reverse) {
return reverse ? a > b : b < a;
};
for (int i = 0; i < size; i++) {
int current = a[i];
cout << current <<endl;
int j = i-1;
while (j >= 0 && comp(current, a[j], reverse)) {
a[j+1] = a[j]; //shift right
j--;
}
a[j+1] = current;
}
show(a, size); //another function which prints all elements of a
}
but if I change
auto comp = [](int a, int b, bool reverse) {
with
bool comp = [](int a, int b, bool reverse) {
GCC compiler throws following error while compiling
error: 'comp' cannot be used as a function 29 | while (j >= 0 && comp(current, a[j], reverse)) {
So is this expected? What is general rule? Shall I always specify return type as auto?
In the 1st code snippet, comp's type is the type of the lambda, it's a unique unnamed class type, (that's why we use auto, we can't specify the type explicitly). Note that it's not the return type of the lambda (i.e. bool).
If you want to specify the return type of the lambda explicitly you can
auto comp = [](int a, int b, bool reverse) -> bool {
// ^^^^^^^
BTW: Non-capturing lambdas could convert to function pointer and then convert to bool implicitly. So if you change the type of comp to bool its value is always true. As the error message said, you just can't use it as functor.
When you write auto comp = [](int a, int b, bool reverse) {, comp has the unique type lambda aka, C++ compiler creates a struct names comp. But when you write bool comp = [](int a, int b, bool reverse) {, comp has the type bool and can only take bool values.
I need to create a template function which calls an exchangeable "worker" function over and over again.
template<class F>
int exec(F f) {
long long s = 0;
for(int i=0; i<1000000; i++) {
s += f(i); // many calls to f
}
return s;
}
Now I thought of different possibilities of defining the worker function:
Inline function
inline int fooInline(int a) { return a + 1; }
exec(fooInline);
Function with definition from other compilation unit
int fooSrc(int a);
exec(fooSrc);
Function object
struct FooOp {
int operator()(int a) { return a + 1; }
};
exec(FooOp());
std::function (e.g. bound to an inline function)
std::function<int(int)> fooFnc = std::bind(&fooInline);
exec(fooFnc);
Lambda
auto fooLambda = [](int a) { return a + 1; };
exec(fooLambda);
Temporary lambda
exec([](int a) { return a + 1; });
What are the differences between theses methods? What would be the fastest way? Can I assume that exec(fooInline) will actually inline fooInline?
Within C++ there is no answer to your question which one would be the fastest. You can measure in your particular environment but then again you do not have any guarantees.
The guess would be that the compiler has the biggest chance to inline if it has easy access to the source of the worker function, so inline function or temporary lambda would be the best. But still a decent compiler might inline in all of the methods you listed.
Assume I'm given two unsigned integers:
size_t A, B;
They're loaded out with some random numbers, and A may be larger, equal, or smaller than B. I want to loop from A to B. However, the comparison and increment both depend on which is larger.
for (size_t i = A; i <= B; ++i) //A <= B
for (size_t i = A; i >= B; --i) //A >= B
The obvious brute force solution is to embed these in if statements:
if (A <= B)
{
for (size_t i = A; i <= B; ++i) ...
}
else
{
for (size_t i = A; i >= B; --i) ...
}
Note that I must loop from A to B, so I can't have two intermediate integers and toss A and B into the right slots then have the same comparison and increment. In the "A is larger" case I must decrement, and the opposite must increment.
I'm going to have potentially many nested loops that require this same setup, which means every if/else will have a function call, which I have to pass lots of variables through, or another if/else with another if/else etc.
Is there any tricky shortcut to avoid this without sacrificing much speed? Function pointers and stuff in a tight, often repeated loop sound extremely painful to me. Is there some crazy templates solution?
My mistake, originally misinterpreting the question.
To make an inclusive loop from A to B, you have a tricky situation. You need to loop one past B. So you work out that value prior to your loop. I've used the comma operator inside the for loop, but you can always put it outside for clarity.
int direction = (A < B) ? 1 : -1;
for( size_t i = A, iEnd = B+direction; i != iEnd; i += direction ) {
...
}
If you don't mind modifying A and B, you can do this instead (using A as the loop variable):
for( B+=direction, A != B; A += direction ) {
}
And I had a play around... Don't know what the inlining rules are when it comes to function pointers, or whether this is any faster, but it's an exercise in any case. =)
inline const size_t up( size_t& val ) { return val++; }
inline const size_t down( size_t& val ) { return val--; }
typedef const size_t (*FnIncDec)( size_t& );
inline FnIncDec up_or_down( size_t A, size_t B )
{
return (A <= B) ? up : down;
}
int main( void )
{
size_t A = 4, B = 1;
FnIncDec next = up_or_down( A, B );
for( next(B); A != B; next(A) ) {
std::cout << A << endl;
}
return 0;
}
In response to this:
This won't work for case A = 0, B = UINT_MAX (and vice versa)
That is correct. The problem is that the initial value for i and iEnd become the same due to overflow. To handle that, you would instead use a do->while loop. That removes the initial test, which is redundant because you will always execute the loop body at least once... By removing that first test, you iterate past the terminating condition the first time around.
size_t i = A;
size_t iEnd = B+direction;
do {
// ...
i += direction;
} while( i != iEnd );
size_t const delta = size_t(A < B? 1 : -1);
size_t i = A;
for( ;; )
{
// blah
if( i == B ) { break; }
i += delta;
}
What are you going to do with the iterated value?
If this is going to be some index in an array, you should use the relevant iterator or reverse_iterator class, and implement your algorithms around these. Your code will be more robust, and easier to maintain or evolve. Besides, a lot of tools in the standard library are built using these interfaces.
Actually, even if you don't, you may implement an iterator class which returns its own index.
You can also use a little bit of metaprogramming magic to define how your iterator will behave according to the order of A and B.
Before going further, please consider that this would only work on constant values of A and B.
template <int A,int B>
struct ordered {
static const bool value = A > B ? false: true;
};
template <bool B>
int pre_incr(int &v){
return ++v;
}
template <>
int pre_incr<false>(int &v){
return --v;
}
template <int A, int B>
class const_int_iterator : public iterator<input_iterator_tag, const int>
{
int p;
public:
typedef const_int_iterator<A,B> self_type;
const_int_iterator() : p(A) {}
const_int_iterator(int s) : p(s) {}
const_int_iterator(const self_type& mit) : p(mit.p) {}
self_type& operator++() {pre_incr< ordered<A,B>::value >(p);return *this;}
self_type operator++(int) {self_type tmp(*this); operator++(); return tmp;}
bool operator==(const self_type& rhs) {return p==rhs.p;}
bool operator!=(const self_type& rhs) {return p!=rhs.p;}
const int& operator*() {return p;}
};
template <int A, int B>
class iterator_factory {
public:
typedef const_int_iterator<A,B> iterator_type;
static iterator_type begin(){
return iterator_type();
}
static iterator_type end(){
return iterator_type(B);
}
};
In the code above, I defined a barebone iterator class going accross the values from A to B. There's simple metaprogramming test to determine whether A and B are in ascending order, and pick the correct operator (++ or --) to go through the values.
Finally, I also defined a simple factory class to hold begin and end iterators methods, Using this class let you have only one single point of declaration for your dependent type values A and B (I mean here that you only need to use A and B once for this container, and the iterators generated from there will be depending on these same A and B, thus simplifying code somewhat).
Here I provide a simple test program, outputing values from 20 to 11.
#define A 20
#define B 10
typedef iterator_factory<A,B> factory;
int main(){
auto it = factory::begin();
for (;it != factory::end();it++)
cout << "iterator is : " << *it << endl;
}
There might better ways of doing this with the standard library though.
The issue of using O and UINT_MAX for A and B was brought up. I think it should be possible to handle these cases by overloading the templates using these particular values (left as an exercise for the reader).
size_t A, B;
if (A > B) swap(A,B); // Assuming A <= B, if not, make B to be A
for (size_t i = A; A <= B; ++A) ...
I have following structure
enum quality { good = 0, bad, uncertain };
struct Value {
int time;
int value;
quality qual;
};
class MyClass {
public:
MyClass() {
InsertValues();
}
void InsertValues();
int GetLocationForTime(int time);
private:
vector<Value> valueContainer;
};
void MyClass::InsertValues() {
for(int num = 0; num < 5; num++) {
Value temp;
temp.time = num;
temp.value = num+1;
temp.qual = num % 2;
valueContainer.push_back(temp);
}
}
int MyClass::GetLocationForTime(int time)
{
// How to use lower bound here.
return 0;
}
In above code I have been thrown with lot of compile errors. I think I am doing wrong here I am new to STL programming and can you please correct me where is the error? Is there better to do this?
Thanks!
The predicate needs to take two parameters and return bool.
As your function is a member function it has the wrong signature.
In addition, you may need to be able to compare Value to int, Value to Value, int to Value and int to int using your functor.
struct CompareValueAndTime
{
bool operator()( const Value& v, int time ) const
{
return v.time < time;
}
bool operator()( const Value& v1, const Value& v2 ) const
{
return v1.time < v2.time;
}
bool operator()( int time1, int time2 ) const
{
return time1 < time2;
}
bool operator()( int time, const Value& v ) const
{
return time < v.time;
}
};
That is rather cumbersome, so let's reduce it:
struct CompareValueAndTime
{
int asTime( const Value& v ) const // or static
{
return v.time;
}
int asTime( int t ) const // or static
{
return t;
}
template< typename T1, typename T2 >
bool operator()( T1 const& t1, T2 const& t2 ) const
{
return asTime(t1) < asTime(t2);
}
};
then:
std::lower_bound(valueContainer.begin(), valueContainer.end(), time,
CompareValueAndTime() );
There are a couple of other errors too, e.g. no semicolon at the end of the class declaration, plus the fact that members of a class are private by default which makes your whole class private in this case. Did you miss a public: before the constructor?
Your function GetLocationForTime doesn't return a value. You need to take the result of lower_bound and subtract begin() from it. The function should also be const.
If the intention of this call is to insert here, then consider the fact that inserting in the middle of a vector is an O(N) operation and therefore vector may be the wrong collection type here.
Note that the lower_bound algorithm only works on pre-sorted collections. If you want to be able to look up on different members without continually resorting, you will want to create indexes on these fields, possibly using boost's multi_index
One error is that the fourth argument to lower_bound (compareValue in your code) cannot be a member function. It can be a functor or a free function. Making it a free function which is a friend of MyClass seems to be the simplest in your case. Also you are missing the return keyword.
class MyClass {
MyClass() { InsertValues(); }
void InsertValues();
int GetLocationForTime(int time);
friend bool compareValue(const Value& lhs, const Value& rhs)
{
return lhs.time < rhs.time;
}
Class keyword must start from lower c - class.
struct Value has wrong type qualtiy instead of quality
I dont see using namespace std to use STL types without it.
vector<value> - wrong type value instead of Value
Etc.
You have to check it first before posting here with such simple errors i think.
And main problem here that comparison function cant be member of class. Use it as free function:
bool compareValue(const Value lhs, const int time) {
return lhs.time < time ;
}
class is the keyword and not "Class":
class MyClass {
And its body should be followed by semicolon ;.
There can be other errors, but you may have to paste them in the question for further help.
You just want to make compareValue() a normal function. The way you have implemented it right now, you need an object of type MyClass around. The way std::lower_bound() will try to call it, it will just pass in two argument, no extra object. If you really want it the function to be a member, you can make it a static member.
That said, there is a performance penalty for using functions directly. You might want to have comparator type with an inline function call operator:
struct MyClassComparator {
bool operator()(MyClass const& m0, MyClass const& m1) const {
return m0.time < m1.time;
}
};
... and use MyClassComparator() as comparator.