Functors with state - 4 (alternative solution using stable_partition)

The is the fourth installment in this series - Functors with state - 1.

Here, what we shall try to do is meet the requirements with a different algorithm. This algorithm does not suffer from the problem that remove_if does as explained in here - Functors with state - 2. But can we be real sure that it is only associated with remove_if and not any of the other algorithms using state maintaining function objects? Well, lets leave that for now.

In this alternate solution, I shall exploit the std::stable_partition algorithm that will help us partition the vector contents based on a predicate test and give the iterator to the element at the partition point. Here is the code that shows how to achieve it.

[CODE]

#include<algorithm>
#include<vector>
#include<iostream>

template<typename T>
struct IsEvenIndex{
               private:
                               mutable/*static*/ typename std::vector<T>::size_type index;
               public:
                               bool operator()(const T& t) const{
                                               if (index%2==0){
                                                               ++index;
                                                               return true;
                                               }else{
                                                               ++index;
                                                               return false;
                                               }
                               }
};

//template<typename T>
//typename std::vector<T>::size_type IsEvenIndex<T>::index=0;

template<typename T>
void PrintVector(const std::vector<T>& t){
               std::cout << std::endl << "Printing vector contents" << std::endl;
               for(typename std::vector<T>::size_type i=0; i<t.size(); ++i){
                               std::cout << t[i] << '\t';
               }
               std::cout << std::endl << std::endl;
}

int main(){
               std::vector<int> myintVector;
               std::vector<int> myanotherintVector;
               for(int i=1; i<=10; ++i){
                       myintVector.push_back(i*10);
               }
               PrintVector(myintVector);
               //std::vector<int>::iterator itend = std::remove_if(myintVector.begin(), myintVector.end(), IsEvenIndex<int>(myotherintVector));
               std::vector<int>::iterator itend = std::stable_partition(myintVector.begin(), myintVector.end(), IsEvenIndex<int>());
               
               PrintVector(myintVector);
               myanotherintVector.assign(itend, myintVector.end());
               myintVector.erase(itend, myintVector.end());
               PrintVector(myintVector);
               PrintVector(myanotherintVector);
}

[OUTPUT]

Printing vector contents
10 20 30 40 50 60 70 80 90 100
Printing vector contents
10 30 50 70 90 20 40 60 80 100
Printing vector contents
10 30 50 70 90
Printing vector contents
20 40 60 80 100


Also, note here that we don't use a static state variable anymore. Just because of the fact that stable_partition does not suffer from the issue that remove_if suffers from due to the call to find_if, passing the predicate by value.

There is another way where we can improve our original code with the static state variable. To remove the static declaration what we do is change the predicate a little as follows:

[CODE]

template<typename T>
struct IsEvenIndex
{
        private:
                 mutable typename std::vector<T>::size_type index;
                 typename std::vector<T>::size_type & index_ref;
                 std::vector<T>& refVec;
        public:
                 bool operator()(const T& t) const
                 {
                          if ( 1 & index_ref++ ) // if it is odd, increment after statement
                          {
                                   return false;
                          }
                          else
                          {
                                   refVec.push_back( t );
                                   return true;
                          }
                 }

        explicit IsEvenIndex(std::vector<T>& vec)
        : refVec(vec), index(0), index_ref( index )
        {}
};

Testing is an exercise and dissecting the logic is what I shall leave for my blog readers and close the topic here with a few references:

1. Codeguru thread where I came across this problem
2. Article that suffices the reasoning
3. Herb Sutter - Extending the standard library

Functors with state - 3 (print contents of vector using std::copy)

I had discussed an issue with function objects containing state and the problems they lead to (especially for std::remove_if algorithm) because of copy creation of those due to argument passing by value. The way they should be passed around is not guranteed by the standards. Here is the starting point for that discussion - Functors with state - 1.

There can be multiple things that can be improved in that code. The first one that I will pick up is the way the function "PrintVector" is laid down.

[CODE]

template<typename T>
void PrintVector(const std::vector<T>& t){
        std::cout << std::endl << "Printing vector contents" << std::endl;
        for(typename std::vector<T>::size_type i=0; i<t.size(); ++i){
                 std::cout << t[i] << '\t';
        }
        std::cout << std::endl << std::endl;
}

There are problems with this code. It is not flexible enough to let you choose the stream where you want the output to be pushed. Secondly, it uses loops and that loop leads to a third problem and that is the repeated call to vector<T>::size() function.

When we have algorithms at our disposal and feel they can improve the code, we should use them. Here is a better way to write the PrintVector function:

[CODE]

#include<vector>
#include<iostream>
#include<algorithm>
#include<iterator>
#include<string>

template<typename T>
void PrintVector(std::ostream& ostr, const std::vector<T>& t, const std::string& delimiter){
        std::copy(t.begin(), t.end(), std::ostream_iterator<T>(ostr, delimiter));
}

A simple one liner!

Another way to better it could be making it independent of the container type. Currently it would work for std::vector only (as demanded as the second argument). We can use iterator inputs (forward iterators should suffice). Here:

[CODE]

#include<iostream>
#include<algorithm>
#include<iterator>
#include<string>

template<typename T, typename InputIterator>
void Print(std::ostream& ostr, InputIterator itbegin, InputIterator itend, const std::string& delimiter){
        std::copy(itbegin, itend, std::ostream_iterator<T>(ostr, delimiter));
}

Now, this Print template can be used to print contents of any sequence that supports input iterators i.e. std::vector, std::deque, std::list, std::string and even plain arrays. The output stream can be anything, a file or the console or anything deriving from std::ostream and similarly we have generalized the delimiter between two subsequent elements that previously was a tab to any string.

More, later! Have fun!!

(Next installment here - Functors with state - 4)

BASIC and Web 2.0

Run BASIC has been called a Web 2.0 BASIC by several people now. I have been pretty much avoiding that classification (lately) because I don't think it meets that description, yet.

One idea that is important for Run BASIC to be a Web 2.0 system is that it needs to be able to consume information from other internet sources. The ability for the user to write a program that downloads the contents of a web page and then process that as information, or the ability to read RSS feeds as data would get us partway there.

I'd be interested in the reader's thoughts about this (yes, you!).

Quiz : function pointers as template arguments

Yesterday, I came across a piece of template code that took me a little by surprise (because I had not come across something like this before) but I was able to put my reasoning through. I will share the code first:

[CODE]

#include <iostream>

template<typename T>
void foo(const T&)
{
               std::cout << "const";
}

template<typename T>
void foo(T&)
{
               std::cout << "non-const";
}

void bar() { }

int main()
{
               foo(bar);
}

The question was - what would the program print? Will the argument "bar" resolve as a parameter to the first template having argument type "const F&" or to the second template having non-const argument type "F&"?

The easiest way to check for the resolution is to ask for explicit template instantiation of the "foo" function template. How? Here is how:

[CODE]

int main()
{
               typedef void (*f_ptr)(); //create a typedef for functions like bar
                                                               //taking no arguments and having return type as void.
               foo<const f_ptr>(bar); //1
               foo<f_ptr>(bar); //2
}

After that, just remove one of the "foo" templates. So, the code to check for compilation is this:

[CODE]
#include<iostream>

template<typename T>
void foo(T&)
{
               std::cout << "non-const";
}

void bar() { }

int main()
{
               typedef void (*f_ptr)(); //create a typedef for functions like bar
                                                               //taking no arguments and having return type as void.
               foo<const f_ptr>(bar); //1
               foo<f_ptr>(bar); //2
}


If you removed the second template, code compiles fine. But if you kept the second one and removed the first one, you will see that the compilation fails for mis-match in the argument type in statement "//2".

Problem solved. Isn't it? What does this tell about the argument "bar" ? It tells that it is a constant. And hence the call in the initial sample code would resolve to the template instance having the argument type declared const. It is in a way similar to any other type constants, for example 5, 100, 2000 are integral constants, they are literals. And when you declare something as say int i; here i is a variable that can be modified. but 5, 100, or 2000 cannot be. In our initial code, both the templates were capable of instantiating the right function for the argument. In both's presence, the argument match has to be exact and hence instantiation happens from the const one but in its absense the instantiation can happen even with the non-const one as the call can help the template to instantiate over type const f_ptr instead of just f_ptr (which is the case for the const one).

Functions pointers when being passed by taking the address of the function directly is a value of const function pointer type.

Functors with state - 2

I was discussing about a problem here - Functors with State - 1

In continuation, there is a striking point in the functor I used. The member variable "index" is static. Why is it static? I did not know why I did that but at my first attempt I did not put it that way. I had kept it as a mutable non-static member variable. Here is how:

[CODE]

template<typename T>
struct IsEvenIndex{
               private:
                               mutable /*static*/ typename std::vector<T>::size_type index;
                               std::vector<T>& refVec;
               public:
                               bool operator()(const T& t) const{
                                               if (index%2!=0){
                                                               ++index;
                                                               return false;
                                               }else{
                                                               ++index;
                                                               refVec.push_back(t);
                                                               return true;
                                               }
                               }
                               IsEvenIndex(std::vector<T>& vec) : refVec(vec), index(0) {}
};

//template<typename T>
//typename std::vector<T>::size_type IsEvenIndex<T>::index=0;


But this created a problem. A problem that was reflected in the output of the program I showed earlier. Here is the output that I got using the above functor.

[OUTPUT]

Printing vector contents
10 20 30 40 50 60 70 80 90 100
Printing vector contents
30 50 70 90
Printing vector contents
10 20 40 60 80 100


Now, you must be wondering about what happened to the first element 10? It is in a different sequence now!

Also, insert (a suggestion for way to improve the code I presented earlier) did not work well, which led me to keep a reference to 2nd vector in the functor: [EDIT : clarification added : the functor used for this main is the first one (from the part 1 of this series) that had the static index member and not the one posted above]

[CODE]

int main(){
               std::vector<int> myintVector;
               std::vector<int> myotherintVector;
               std::vector<int> myanotherintVector;
               for(int i=1; i<=10; ++i){
                       myintVector.push_back(i*10);
               }
               PrintVector(myintVector);
               std::vector<int>::iterator itend = std::remove_if(myintVector.begin(), myintVector.end(), IsEvenIndex<int>(myotherintVector));
               myanotherintVector.insert(myanotherintVector.begin(), itend, myintVector.end());
               myintVector.erase(itend, myintVector.end());
               PrintVector(myintVector);
               PrintVector(myotherintVector);
               PrintVector(myanotherintVector);
}


It gave the following flawed output:

[OUTPUT]

Printing vector contents
10 20 30 40 50 60 70 80 90 100
Printing vector contents
20 40 60 80 100
Printing vector contents
10 30 50 70 90
Printing vector contents
60 70 80 90 100

What a mess! Isn't it? The functor can be improved to keep a bool toggling member rather than an int but I guess that would suffer the same issue. Try it out and let me know if it doesn't!

The static member variable seems like a necessity. I could not do without it!

The basic problem is using remove_if with a predicate having non-static state! There can be many different implementations of remove_if. There can be cases where remove_if calls another helper algorithm passing the predicate. Now, how would this predicate be passed? By reference or by value? This is unspecified by the standards. And this is the problem that has been haunting us! Our predicate contains state, an integer value. The implementations that I ran my sample codes above, used to call find_if first passing the predicate by value. When passed by value a copy is created, right? Now, it constructs the state with the default state and moves through a few elements until a match is found incrementing the state but when the control returns from the find_if algorithm, that changed state is not transferred to remove_if! That is the problem. The state here remains the initial one as before the call to find_if. And it proceeds with that "wrong" state forward. Surely, it will mess up things and as a fix that is the state that we maintained between those calls when we declared the member variable as static! Mystery solved!

Alternative solutions and how to make that code better comes in later posts! Keep having fun!

(Next installment here - Functors with state - 3)

Functors with state - 1

Some time back, I had come across a small problem to which I tried writing out a solution. The problem and the solution both were simple but there was something that I learnt that can mess your code and you will have little idea about it.

The problem was to split a vector of integers into 2 vectors of integers. The first one would contain the elements at odd indexes and second one would contain the elements at the even indexes.

Here is a solution that I had provided:

[CODE]

#include<algorithm>
#include<vector>
#include<iostream>

template<typename T>
struct IsEvenIndex{
               private:
                               static typename std::vector<T>::size_type index;
                               std::vector<T>& refVec;
               public:
                               bool operator()(const T& t) const{
                                               if (index%2==0){
                                                               ++index;
                                                               refVec.push_back(t);
                                                               return true;
                                               }else{
                                                               ++index;
                                                               return false;
                                               }
                               }
                               IsEvenIndex(std::vector<T>& vec) : refVec(vec){}
};

template<typename T>
typename std::vector<T>::size_type IsEvenIndex<T>::index=0;

template<typename T>
void PrintVector(const std::vector<T>& t){
               std::cout << std::endl << "Printing vector contents" << std::endl;
               for(typename std::vector<T>::size_type i=0; i<t.size(); ++i){
                               std::cout << t[i] << '\t';
               }
               std::cout << std::endl << std::endl;
}

int main(){
               std::vector<int> myintVector;
               std::vector<int> myotherintVector;
               for(int i=1; i<=10; ++i){
                       myintVector.push_back(i*10);
               }
               PrintVector(myintVector);
               std::vector<int>::iterator itend = std::remove_if(myintVector.begin(), myintVector.end(), IsEvenIndex<int>(myotherintVector));
               myintVector.erase(itend, myintVector.end());
               PrintVector(myintVector);
               PrintVector(myotherintVector);
}


The inlined comments explain the things being done quite clearly. All is fine and well and we get the output as expected. Here is the sample outout that I got:

[OUTPUT]

Printing vector contents
10 20 30 40 50 60 70 80 90 100
Printing vector contents
20 40 60 80 100
Printing vector contents
10 30 50 70 90

There are better ways to do this, of course. The easiest would be to iterate the initially populated vector and alternately keep populating two other vectors to contain the result-sets.

There can be improvements to the functor as well. By removing the push_back from the functor to an insert function that populates the 2nd vector from the removed elements from first vector, followed by an erase call.

But let's not deviate. There is a point of concern in the above code that will lead you to the point of discussion that I wanted to concentrate on.

To be continued in Functors with state - 2. Later!

Constructor templates and explicit instantiation

Well, this is going to be a lighter one. I came across this recently. Classes can have templates and constructors can be templates too. Something like this:

[CODE]

class SomeClass
{
             public:
                           template<typename T>
                           SomeClass(T t) { /*some code*/ }
};

Now, we all know that we can explicitly ask the compiler to generate the code for a specific template type parameter T of any class or any function template. But is the same possible for constructors? Let's try:

[CODE]

int main()
{
             SomeClass object<int>(10);
             SomeClass object.template SomeClass<int>(10);
}


Try compiling the code. It doesn't. Isn't it? You may try different ways, different syntaxes but the thing is you cannot ask a explicit instantiation of templatized constructors. The reason being that constructors are typical member functions. They are called without a function name. They don't have a name. I mean, they are declared by the same name as that of the class but in user code sense, they don't have a name using which they are invoked. In fact, they are not even invoked by us. That happens automatically or by the placement new syntax but you don't specify the name and hence the arguments (template arguments or function arguments).

Similar are conversion functions. Here is a note from the C++ standards 2005 draft that is quite self-explantory: (section 14.8.1 paragraph 7)

[NOTE]

[ Note: because the explicit template argument list follows the function template name, and because conversion member function templates and constructor member function templates are called without using a function name, there is no way to provide an explicit template argument list for these function templates. —end note ]

Have fun! More, later...

Run BASIC Two Weeks Report

Well, Run BASIC (http://www.runbasic.com) has been online now for slightly more than 2 weeks. We've had more than 1500 unique visitors.

There have been a handful of server crashes in that period and numerous bugfixes. A few of these fixes are related to stability of the server but most are new features or fixes in the compiler or runtime system. This is a very good thing since most of this stuff feeds directly into the Liberty BASIC v5.0 effort. In essence this is a kind of alpha testing for LB5.

The community has responded nicely by creating a Run BASIC section on the Liberty BASIC Conforums site and by putting up a wiki. People have been busy creating programs that run under Run BASIC. Thanks to all of you for that.

Where are we headed with this? We have just started work on a Run BASIC personal edition. This will be a special version of the software that you can install on your own computer. Windows, Mac and Linux will all be supported. The user interface for this will still be web based, but it will be more of an IDE style setup. Our idea is that you can use this system to host a web site and share programs that you write as links on a home page. We are thinking a license for this system will cost $20 to $30.

Once the personal system is launched, we plan to create an educational system for instructors. Each student can have an account, and they can work through their lessons in their browsers whether at home, at school, or wherever they can access the server by means of the internet. Access to student work will be managed for the instructor automatically. We'll develop these ideas more later on.

Binders

I came across a bug with the binders. Had heard from people that the standard ones are not very effective and buggy and boost binders should be used. But I realized it recently why that's said.

Here is a piece of code that should work but does not, why? Because STL bind2nd works with const member functions and NOT the non-const member functions. The code first:

[CODE]
        size_t N = 1000;
        vector<vector<int> > v(N);
        for_each(v.begin(), v.end(), bind2nd(mem_fun_ref(&vector<int>::reserve)),N));


Another sample to test:

[CODE]
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;

struct Test
{
             void func1(int){}
             void func2(int)const{}
};

int main()
{
             size_t N=100;
             vector<Test> TestVectorObject(N);
             for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func1),N)); //ERROR
             for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func2),N)); //OK
}


Try compiling with online Comeau here - Online Comeau Compiler and see for yourself. The above code will compile fine but just comment the const version and uncomment the non-const version and see. The code will fail to compile.

So, what's the solution? Two possible solutions come to my mind. The first would need you to write a functor whose operator() takes each object of the vector and calls the required member function. The other is to use tr1::bind.

Here are the relevant codes for the two solutions that I talked about.

Solution (using explicit functor)
[CODE]
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;

template<typename T>
struct CallNonConstFunc1
{
               void operator() (T& obj) const
               {
                               obj.func1(int());
               }
};


struct Test
{
               void func1(int){}
               void func2(int)const{}
};

int main()
{
               size_t N=100;
               vector<Test> TestVectorObject(N);
               //for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func1),N));
               for_each(TestVectorObject.begin(), TestVectorObject.end(), CallNonConstFunc1<Test>());
               for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func2),N));
}

Not very elegant, isn't it? So, lets see how tr1::bind does it...

Solution (using tr1::bind)
[CODE]
#include<vector>
#include<algorithm>
#include<functional>

using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;

template<typename T>
struct CallNonConstFunc1
{
               void operator() (T& obj) const
               {
                               obj.func1(int());
               }
};

struct Test
{
               void func1(int){}
               void func2(int)const{}
};

int main()
{
               size_t N=100;
               vector<Test> TestVectorObject(N);
               for_each(TestVectorObject.begin(), TestVectorObject.end(), bind(mem_fun_ref(&Test::func1),_1,N));
               for_each(TestVectorObject.begin(), TestVectorObject.end(), CallNonConstFunc1<Test>());
               for_each(TestVectorObject.begin(), TestVectorObject.end(), bind2nd(mem_fun_ref(&Test::func2),N));
}

Try compiling that correction with Dinkumware online compiler here - Dinkumware Exam (online compiler)

References:

-- Scott Meyers : tr1 Information - TR1 Information - Scott Meyers
-- Dinkumware : tr1 - Dinkumware TR1 Documentation
-- Pete Becker : C++ Function Objects in TR1 - C++ Function Objects in TR1 - Pete Becker

Have fun!

Check out this stream