Common Programming Language Features

Common Pitfalls
C++ declarations: int x;             // declare x of type int int x(7);          // declare x of type int and initialize to 7 int x;           // declare FUNCTION x(void) => int int *x = new int; // declare x of type int *

C++ weird scope resolution: class foo {};

class bar { int foo; // a member function named like a class //foo f; // syntax error : missing ';' before identifier 'f'   ::foo f; // specify scope to avoid error };

C++ pointer containers: boost::ptr_map does not support abstract classes.

boost::ptr_map can be emulated using a combination of std::map and boost::ptr_list (or another non-associative container).

Elements in  cannot be removed or found by their address. See the Boost Pointer Container Library page for a workaround.

C++ algorithms:
 * the remove algorithm does not remove anything, it moves 'unremoved' elements to the front of a container.
 * erase really removes elements
 * list::remove also erases the elements


 * erase means

Automatic String Conversion
C#: class MyClass { public string ToString { return "MyClass instance"; } } ... MyClass myClass = new MyClass; System.Console.WriteLine("myClass: " + myClass.ToString); C++: namespace Some_namespace { using std::ostream; class My_class { friend ostream & operator << (ostream &, const My_class &); }; } // Drop overloaded ostream operator in global namespace ostream & operator <<(ostream & os, const Some_namespace::My_class &my_class) { return os << "My_class instance"; } using namespace std; int main { Some_namespace::My_class my_class; cout << "my_class: " << my_class << endl; } Ruby: class My_class def to_s "My_class instance" end end my_class = My_class.new puts "my_class: " + my_class
 * 1) include

Regular Expressions
C#: using System.Collections.Generic; using System.Text.RegularExpressions;

class RegexTest { static void Main { List words = new List { "HEJ", "Hello", "yo" }; Regex acceptedWordRegex = new Regex("he.*", RegexOptions.IgnoreCase); Regex wordSubstitutionRegex = new Regex("(^.)e(.*)", RegexOptions.IgnoreCase); foreach(string word in words) { if(acceptedWordRegex.IsMatch(word)) { string s = wordSubstitutionRegex.Replace(                   word, "$2e$1"); System.Console.WriteLine(s); }	}   } } C++:
 * 1) include 
 * 2) include 
 * 3) include

using namespace std;

int main { char *words[] = { "HEJ", "Hello", "yo" }; boost::regex accepted_word_regex("he.*", boost::regex::icase); boost::regex word_substitution_regex("(^.)e(.*)", boost::regex::icase);

BOOST_FOREACH(char *word, words) { if(regex_match(word, accepted_word_regex)) { string s = regex_replace(string(word),		          word_substitution_regex, string("\\2e\\1"),			   boost::match_default); cout << s << endl; }   } }

Ruby: words = [ "HEJ", "Hello", "yo" ] words.each { |word| if word =~ /he.*/i then puts word.gsub(/(^.)e(.*)/i,'\2e\1') end }

Directory Iteration
C++ using namespace boost::filesystem;
 * 1) include 

const path & my_path; assert( exists( my_path ) ); directory_iterator end_itr; // default construction yields past-the-end for(directory_iterator itr(my_path); itr != end_itr; ++itr ) cout << itr->filename << endl;

Writing Files
C#: using System.IO; // ... Directory.CreateDirectory("/tmp/filetest"); using (StreamWriter sw = new StreamWriter("/tmp/filetest/testfile")) { sw.WriteLine("yo"); } if(File.Exists("/tmp/filetest/testfile")) Console.WriteLine("we have created a file"); C++: // link with boost_filesystem and boost_system
 * 1) include "boost/filesystem.hpp"
 * 2) include
 * 3) include

using namespace boost::filesystem; using namespace std;

int main { create_directory("/tmp/filetest"); ofstream file("/tmp/filetest/testfile"); file << "yo" << endl; file.close; if(exists("/tmp/filetest/testfile")) cout << "we have created a file" << endl; } Ruby: require 'fileutils' include FileUtils mkdir_p "/tmp/filetest" IO.popen("/tmp/filetest/testfile") { |f| f.puts "yo" } if File.exists?("/tmp/filetest/testfile") then puts "we have created a file" end

Sleeping For 1.5 Seconds
C++: using namespace boost; this_thread::sleep(posix_time::seconds(1.5f));
 * 1) include 
 * 2) include 

Record Time
C++: boost::timer timer; // Time elapsed since construction. double elapsed_time__s = timer.elapsed;
 * 1) include 

Dynamic Array
C#: using System.Collections.Generic; List numbers(1); numbers.Add(10); numbers.Add(23); // reallocate C++ with value semantics: using std::vector; vector numbers(1); numbers.push_back(10); numbers[1] = 23; // reallocate C++ with pointer semantics: using boost::ptr_vector; struct Thing { Thing(int x) : x_(x) {} int x_; }; ptr_vector things(1); things.push_back(new Thing(10)); things[1] = new Thing(23); // reallocate Ruby: numbers = Array.new(1) numbers.push(10) numbers[1] = 23
 * 1) include
 * 1) include 

Linked List
C++: using namespace std; list l; l.push_back(4); l.push_back(9); l.remove(4); // list::remove both removes and erases
 * 1) include
 * 2) include

// Filter based upon arbitrary predicate. Note that due to a // weirdness in C++98, you cannot use local classes as predicates. struct Larger_than { Larger_than(int value) : value(value) {} inline bool operator (int value_to_check) const { return value_to_check > value; }   int value; }; l.remove_if(Larger_than(5)); // both removes and erases

struct Is_even { inline bool operator (int value_to_check) const { return value_to_check % 2 == 0; } }; l.remove_if(Is_even);

// search for value list ::iterator i = find(l.begin, l.end, 7); if(i == l.end) { // couldn't find 7 } else { // found it }

Associative Array
C#: using System.Collections.Generic; // ... Dictionary name2thing = new Dictionary; name2thing["thing 1"] = new Thing("hey"); name2thing["thing 2"] = new Thing("there"); name2thing.Remove("thing 1"); if(name2thing.ContainsKey("thing 1") { ... } foreach(string s in name2thing.Keys) {   System.Console.WriteLine(name2thing[s].Name); } C++: using namespace std; // ... typedef map Name_2_thing; typedef Name_2_thing::iterator Name_2_thing_iterator; Name_2_thing name_2_thing; name_2_thing["thing 1"] = new Thing("hey"); name_2_thing["thing 2"] = new Thing("there"); name_2_thing.erase("thing 1");
 * 1) include
 * 2) include
 * 3) include
 * 4) include 

// find member Name_2_thing_iterator i = name_2_thing.find("thing 1"); if(i == name_2_thing.end) { // handle error: no such key } else { Thing * thing = i->second; }

// delete member Name_2_thing_iterator i = name_2_thing.find("thing 1"); if(i == name_2_thing.end) { // handle error: no such key } else { name_2_thing.erase(i); }

BOOST_FOREACH(Name_2_thing::value_type &i, name_2_thing) { cout << i.second->get_name << endl; } Ruby: // ... name_2_thing = {} name_2_thing["thing 1"] = Thing.new("hey") name_2_thing["thing 2"] = Thing.new("there") name_2_thing.delete("thing 1") if name_2_thing.has_key?("thing 1") then ... end name_2_thing.each do |name,thing| puts thing.name end

Class Definition
C#: namespace MyNamespace { class MyClass { int someValue;

MyClass(int someValue) { this.someValue = someValue; }       ~MyClass { System.Console.WriteLine("destroyed."); }       public int SomeValue { get { return someValue; } set { someValue = value; } }       private void something {} static void Main { MyNamespace.MyClass mc = new MyNamespace.MyClass(7); System.Console.WriteLine(mc.SomeValue); }      }   }   C++: namespace My_namespace { class My_class { public: My_class(int some_value) : some_value(some_value) {} ~My_class { std::cout << "destroyed." << std::endl; }       int some_value { return some_value; } void some_value(const int &new_value) { some_value = new_value; } private: void something {} int some_value; } }; int main { My_namespace::My_class mc = new My_namespace::My_class; std::cout << mc->my_method << std::endl; delete mc; } Ruby: module My_namespace class My_class attr_accessor :some_value def initialize(some_value) @some_value = some_value end def release_resources # not destructor puts "destroyed." end def something end end end mc = My_namespace::My_class.new(7) puts mc.some_value mc.release_resources # manually calling cleanup method
 * 1) include

Virtual Methods
C#: class Something

Factory Method
C++:

Returning a new Thing could just as well be done using a raw pointer. The caller could then store the pointer in a smart pointer or deallocate using delete. However, it is not explicit in the interface that the caller has to handle resource deallocation.

Using shared_ptr forces the caller to handle the memory correctly.
 * 1) include

using namespace std;

class Thing { public: virtual ~Thing { ... }

// Named ctor. static shared_ptr create_thing { return shared_ptr( new Thing(7) ); }   // Named ctor. static shared_ptr create_special_thing { return shared_ptr( new Thing(60) ); }   // Virtual copy ctor. virtual shared_ptr<Thing> clone { return shared_ptr<Thing>( new Thing(* this) ); } protected: // Private ctor accessed by factory methods. Thing(int x) : x_(x) { } // Private copy ctor accessed by clone. Thing( const Thing & other) : x_(other.x_) { } private: int x_; };

class Thingie : public Thing { public: // Named ctor. static shared_ptr<Thingie> create_thingie { return shared_ptr<Thingie>( new Thingie(70) ); }   // Virtual copy ctor. virtual shared_ptr<Thing> clone { return shared_ptr<Thing>(new Thingie( * this )); } private: // Private ctor accessed by factory methods. Thingie( int x ) : Thing(x) { } Thingie( const Thingie & other ) : Thing(other.x_) { } };

int main { shared_ptr<Thing> t0 = Thing::create_thing; shared_ptr<Thing> t1 = Thing::create_special_thing; shared_ptr<Thing> t2 = t1->clone;

shared_ptr<Thing> t3 = Thingie::create_thing; shared_ptr<Thing> t4 = t3->clone; }

Named Parameter
Ruby: def do_stuff(unnamed_parameter, opts={}) opts = {:named_parameter => 8, :other_named_parameter => true}.merge(opts) # default argument values if opts[:other_named_parameter] then ...    else ...    end end

Observer
In C#, the Observer pattern is implemented as events.

C#: class Subject { public delegate void SomeEventHandler(int someValue); public event SomeEventHandler SomeEvent; protected void doSomething { if(SomeEvent != null) SomeEvent(7); } }

class Observer { public Observer(Subject subject) { subject.SomeEvent += myHandler; }   void myHandler(int someValue) { // ...   } } In C++, boost::signal implements the Observer pattern.

C++:
 * 1) include <boost/signal.hpp>
 * 2) include <boost/bind.hpp>

class Subject { public: boost::signal<void (int)> some_event; protected: void do_something { some_event(7); } }; class Observer { public: Observer(subject &subject) { subject.some_event.connect(boost::bind(& observer::my_handler, this, _1)); }   void my_handler(int some_value) { // ...   } }; In Ruby, observer.rb implements the Observer pattern. require 'observer'

class Subject include Observable # mixin def do_something changed # note that our state has changed notify_observers( 7 ) end end class Observer class My_handler # the invoked method must be 'update' def update(some_value) # ...       end end def initialize(subject) subject.add_observer(My_handler.new) end end