Tag Archive : programming

/ programming

New Initialization Forms in C++11

December 5, 2015 | Article | No Comments

In C++11, initializing objects, arrays, and containers will become much easier than it used to be in C++03. In this article we will discuss about the use of new brace-initialization notation, class member initializers, and initialization list to write better and shorter code without compromising code safety or efficiency.

Initialization in C++03 is tricky with four different initialization notations and far too many arbitrary restrictions and loopholes:

  • No way to initialize a member array
  • No convenient form of initializing containers
  • No way to initialize dynamically allocated POD types

C++11 fixes these problems with new facilities for initializing objects. In this article, I present the new C++11 brace-initialization notation, discuss class member initialization, and explain how to initialize containers by using initializer lists.

C++03 Initialization: Four Initialization Notations

First let’s look at the C++03 initialization form. C++03 has various categories of initialization:

    • Initialization of fundamental types. The initialization of fundamental types uses the equal sign (=):
int n=0;
void*p=0;
char c='A';
    • Initialization of data members in a class and objects. Classes with a user-defined constructor require a constructor’s member initialization list (mem-init for short) for their data members. An object’s initializers are enclosed in parentheses in the object’s declaration:
//C++03 initialization of classes and objects
struct S1
{
  explicit S1(int n, int m) : x(n), y(m){} //mem-init
private:
  int x, y;
};

S1 s(0,1); //object initializers enclosed in parentheses
S1 s2={0,1}; //compilation error
    • Initialization of aggregates. Aggregate initialization requires braces, with the exception of string literals that may also appear between a pair of double quotes ([dp][dp]):
//C++03: POD arrays and structs are aggregates
int c1[2]={0,2};
char c2[]="message";
//or you can use the more verbose form:
char c3[]={'m','e','s','s','a','g','e','\0'};

struct S
{
  int a,b;
};

S s={0,1};

We also can use parentheses to initialize fundamental types as well. The parentheses in this case are interchangeable with the equal sign notation:

int n(0); //same as int n=0;
double d(0.5);

C++03 Initialization: Arbitrary Restrictions and Loopholes

C++03 imposes arbitrary restrictions in some cases, such as the inability to initialize member arrays:

class C
{
  int x[100];
  C(); //no proper way to initialize x
};

Similarly, we can’t initialize a dynamically allocated POD array:

char *buff=new char[1024]; //no proper way to initialize the elements of buff

Finally, there’s no easy way to initialize the elements of a Standard Library container. For instance, if you want to initialize a vector of strings, we would normally use a sequence of push_back() calls like this:

vector <string> vs;
vs.push_back("alpha");
vs.push_back("beta");
vs.push_back("gamma");

Fairly say, C++03 initialization is a mess. Now let’s see how C++11 tackles these problems with its new and uniform initialization notation.

Introducing C++11 Brace-Initialization

C++11 attempts to overcome the problems of C++03 initialization by introducing a universal initialization notation that applies to every type—whether a POD variable, a class object with a user-defined constructor, a POD array, a dynamically allocated array, or even a Standard Library container. The universal initializer is called a brace-init. It looks like this:

//C++11 brace-init
int a{0};
string s{"hello"};
string s2{s}; //copy construction
vector <string> vs{"alpha", "beta", "gamma"};
map<string, string> engineers
{ {"Satria", "+62 8977423935"},
  {"Ady", "++62 8977423936"}
};
double *pd= new double [3] {0.5, 1.2, 12.99};

class C
{
  int x[4];
public:
  C(): x{0,1,2,3} {}
};

 

Notice that unlike the traditional aggregate initializer of C and C++03, which uses braces after an equal sign (={}), the C++11 brace-init consists of a pair of braces (without the equal sign) in which the initializer(s) will be enclosed. An empty pair of braces indicates default initialization. Default initialization of POD types usually means initialization to binary zeros, whereas for non-POD types default initialization means default construction:

//C++11: default initialization using {}
int n{}; //zero initialization: n is initialized to 0
int *p{}; //initialized to nullptr
double d{}; //initialized to 0.0
char s[12]{}; //all 12 chars are initialized to '\0'
string s{}; //same as: string s;
char *p=new char [5]{}; // all five chars are initialized to '\0'

Class Member Initialization

C++11 pulls another rabbit out of its hat with class member initializers. Perhaps an example will best illustrate these:

class C
{
  int x=7; //class member initializer
public:
  C();
};

The data member x is automatically initialized to 7 in every instance of class C. In former dialects of C++, you would use the more cumbersome mem-init notation for the same purpose:

class C
{
  int x;
public:
  C() : x(7) {}
};

C++11 class member initializers are mostly a matter of convenience. They provide an overt and simplified form of initializing data members. But class member initializers also let you perform a few tricks that have hitherto been impossible. For example, you can use a class member initializer to initialize a member array:

class C
{
  int y[5] {1,2,3,4};
public:
  C();
};

Notice that a class member initializer can consist of any valid initialization expression, whether that’s the traditional equal sign, a pair of parentheses, or the new brace-init:

class C
{
  string s("abc");
  double d=0;
  char * p {nullptr};
  int y[5] {1,2,3,4};
public:
  C();
};

Regardless of the initialization form used, the compiler conceptually transforms every class member initializer into a corresponding mem-init. Thus, class C above is semantically equivalent to the following class:

class C2
{
  string s;
  double d;
  char * p;
  int y[5];
  public:
  C() : s("abc"), d(0.0), p(nullptr), y{1,2,3,4} {}
};

Bear in mind that if the same data member has both a class member initializer and a mem-init in the constructor, the latter takes precedence. In fact, you can take advantage of this behavior by specifying a default value for a member in the form of a class member initializer that will be used if the constructor doesn’t have an explicit mem-init for that member. Otherwise, the constructor’s mem-init will take effect, overriding the class member initializer. This technique is useful in classes that have multiple constructors:

class C
{
  int x=7; //class member initializer
  C(); //x is initialized to 7 when the default ctor is invoked
  C(int y) : x(y) {} //overrides the class member initializer
};
C c; //c.x = 7
C c2(5); //c.x = 5

Initializer Lists and Sequence Constructors

An initializer list lets you use a sequence of values wherever an initializer can appear. For example, you can initialize a vector in C++11 like this:

vector<int> vi {1,2,3,4,5,6};
vector<double> vd {0.5, 1.33, 2.66};

You may include as many initializers as you like between the braces. Although superficially this new syntax seems identical to the brace-init notation we discussed earlier, behind the scenes it’s a different story. C++11 furnishes every STL container with a new constructor type called a sequence constructor. A sequence constructor intercepts initializers in the form of {x,y...}. To make this machinery work, C++11 introduced another secret ingredient: an auxiliary class template called std::initializer_list<T>. When the compiler sees an initializer list, say {0.5, 1.33, 2.66}, it transforms the values in that list into an array of T with n elements (n is the number of values enclosed in braces) and uses that array to populate an implicitly generated initializer_list<T> object. The class template initializer_list has three member functions that access the array:

template<class E> class initializer_list
{
  //implementation (a pair of pointers or a pointer + length)
public:
  constexpr initializer_list(const E*, const E*); // [first,last)
  constexpr initializer_list(const E*, int); // [first, first+length)
  constexpr int size() const; // no. of elements
  constexpr const T* begin() const; // first element
  constexpr const T* end() const; // one more than the last element
};

To better understand how the compiler handles initializer lists of containers, let’s dissect a concrete example. Suppose your code contains the following declaration of a vector:

vector<double> vd {0.5, 1.33, 2.66};

The compiler detects the initializer list {0.5, 1.33, 2.66} and performs the following steps:

  1. Detect the type of the values in the initializer list. In the case of {0.5, 1.33, 2.66}, the type is double.
  2. Copy the values from the list into an array of three doubles.
  3. Construct an initializer_list<double> object that “wraps” the array created in the preceding step.
  4. Pass the initializer_list<double> object by reference to vd‘s sequence constructor. The constructor in turn allocates n elements in the vector object, initializing them with the values of the array.

It’s hard to imagine that so much is going on behind the scenes every time you initialize an STL container with a pair of braces! The good news is that you don’t have to do anything for this magic to happen—it just works. Of course, you still need a C++11-compliant compiler as well as a C++11-compliant Standard Library to use initializer lists. Make sure that your target project is built with the appropriate compilation options, too.

Conclusion

The C++ standards committee invested a lot of time and effort in finding a solution to the limitations of C++03 initialization. It looks like they succeeded. Historically, brace-init, class member initializers, and initializer lists were three independent proposals. Later, they were revised to ensure compatibility and uniformity. Together, these three initialization-related features make C++11 programming simpler and more intuitive. You will surely appreciate them next time you initialize a dynamically allocated array—or, indeed, a vector.

Implementation of Delegates in C++11

December 5, 2015 | Article | 1 Comment

Introduction

In C++, it would be useful to be able to bind an object with its member function and produce a global function. Such features exists in other languages, for example C#. In C++, there are member function pointers but they do not provide the feature we talk about. In this article we will discuss about a simple implementation of delegates in C++ using member function pointers and C++11 using variadic templates.

For this article, I use:

  1. Slackware64 14.0 with gcc 4.7.1
  2. Windows 8 with Visual Studio 2010 express

Background

The approach is to provide a function create_delegate, which can be called in one of the following ways:

  • create_delegate(&object, &member_function)
  • create_delegate(&function)

The first option creates an object with a member operator() that can be called as a function. The second produces a function pointer, which is the same as &function. Both these values are compatible with type type function<...>.

A Sample Program

Let’s define a class with several methods

class A {
	int i;
public:
	A(int k):i(k) {}

	auto get()const ->int { return i; }
	auto set(int v)->void { i = v; }

	auto inc(int g)->int& { i+=g; return i; }
	auto incp(int& g)->int& { g+=i; return g; }

	auto f5 (int a1, int a2, int a3, int a4, int a5)const ->int {
		return i+a1+a2+a3+a4+a5;
	}

	auto set_sum4(int &k, int a1, int a2, int a3, int a4)->void {
		i+=a1+a2+a3+a4;
		k = i;
	}

	auto f8 (int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const ->int {
		return i+a1+a2+a3+a4+a5+a6+a7+a8;
	}

	static auto sqr(double x)->double { return x*x; }

	auto g1(const int& n)->void { std::cout << "g1: " << n <<  std::endl; }
	auto g2(int&& n)->void { std::cout << "g2: " << n <<  std::endl; }
	auto g3(int& n)->int&  { n++; return n; }
	auto g4(int n)-<int    { return 10*n; }
};

Please note that in source code above we use C++11 convention using auto and new function declaration syntax. It is not absolutely a requirement to do so, hence you can also define the class using traditional way of declaration like good all C++ program.

In the program, we can create a class as follows:

A a(11)

Now, to create delegates:

[sourcecode language="c++"]
auto set1 = create_delegate(&a,&A::set);
auto inc = create_delegate(&a,&aA::inc);
std::function<int(int&)> incp = create_delegate(&a,&A::incp);
auto af5  = create_delegate(&a,&A::f5);
auto set_sum4= create_delegate(&a,&A::set_sum4);
auto af8  = create_delegate(&a,&A::f8);
auto sqr = create_delegate(&A::sqr); // static function, not a member
auto g1  = create_delegate(&a,&A::g1);
auto g2  = create_delegate(&a,&A::g2);
auto g3  = create_delegate(&a,&A::g3);
auto g4  = create_delegate(&a,&A::g4);
[/sourcecode]

As demonstrated, we can use auto or function<…>. Now we can invoke the delegates:

set1(25);
int x = 5;
int k = inc(x);
int k2 = incp(x);
k2 *= 7;
std::cout << "a.get():" << a.get() << std::endl;
std::cout << "k: " << k << std::endl;
std::cout << "x: " << x << std::endl;
std::cout << "af5(1,2,3,4,5): " << af5(1,2,3,4,5) << std::endl;

set_sum4(x,1,2,3,20);
std::cout << "after set_sum4(x,1,2,3,20)" << std::endl;
std::cout << "a.get(): " << a.get() << std::endl;
std::cout << "x: " << x << std::endl;
std::cout << "af8(1,2,3,4,5,6,7,8): " << af8(1,2,3,4,5,6,7,8) << std::endl;
std::cout << "sqr(2.1): " << sqr(2.1) << std::endl;
g1(100);
g2(32+5);
int p = 15;
int& g = g3(p);
int s = g4(35);
g++;
std::cout << "p: " << p << std::endl;
std::cout << "s: " << s << std::endl;

The program will print:

a.get():30
k: 30
x: 35
af5(1,2,3,4,5): 45
after set_sum4(x,1,2,3,20)
a.get(): 56
x: 56
af8(1,2,3,4,5,6,7,8): 92
sqr(2.1): 4.41
g1: 100
g2: 37
p: 17
s: 350

Points about the implementation

For a simple member function that is not volatile or const, the implementation would be very simple. We have to create a class that will store the two pointers: one to the object and the other to the its member function:

template <class T, class R, class ... P>
struct  _mem_delegate {
	T* m_t;
	R  (T::*m_f)(P ...);
	_mem_delegate(T* t, R  (T::*f)(P ...) ):m_t(t),m_f(f) {}
	R operator()(P ... p) {
			return (m_t->*m_f)(p ...);
	}
};

But the return statement needs some correction. The problem is that if a function has an rvalue-reference argument (like auto g2(int&& n)->void), this will not work. Such a parameter in the body of the function is not an rvalue any more, it’s an lvalue. Then we have two options:

  1. Use forwarding return (m_t->*m_f)(std::forward<P>(p) …);
  2. Just convert using static_cast such that return (m_t->*m_f)(static_cast<P>(p) …);

Both options will work at this point. The first underlines the idea, the second is more general.

The variadic template allows us to define operator() with flexible number and types of parameters. The create_function implementation will simply return an object of this class:

template <class T, class R, class ... P>
_mem_delegate<T,R,P ...> create_delegate(T* t, R (T::*f)(P ...)) {
	_mem_delegate<T,R,P ...> d(t,f);
	return d;
}

Practically, there is needed extra three implementations to cover cases of member functions which are const, volatile and const volatile. That’s why traditional macros, using #define, are handy: they allow us to avoid rewriting the same code fragments. Here is the full implementation:

template <class F>
F* create_delegate(F* f) {
	return f;
}

#define _MEM_DELEGATES(_Q,_NAME)\
template <class T, class R, class ... P>\
struct _mem_delegate ##_NAME\
{\
	T* m_t;\
	R  (T::*m_f)(P ...) _Q;\
	_mem_delegate ##_NAME(T* t, R  (T::*f)(P ...) _Q):m_t(t),m_f(f) {}\
	R operator()(P ... p) _Q\
	{\
		return (m_t->*m_f)(std::forward<P>(p) ...);\
	}\
};\
\
template <class T, class R, class ... P>\
	_mem_delegate ##_NAME<T,R,P ...> create_delegate(T* t, R (T::*f)(P ...) _Q)\
{\
	_mem_delegate ##_NAME<T,R,P ...> d(t,f);\
	return d;\
}

_MEM_DELEGATES(,Z)
_MEM_DELEGATES(const,X)
_MEM_DELEGATES(volatile,Y)
_MEM_DELEGATES(const volatile,W)

A more meaningful example: calculating the length of a curve

In this section we will consider a sample practical problem and look at various approaches, and show some alternative methods to delegates.

Calculation of the length of a curve: global functions

The function CurveLength can be used to calculate the length of a curve, which is defined by two functions fx(t) and fy(t), where t is in the range [a,b]. The parameter n is the number of step we take, and it affects the precision.

auto CurveLength(auto (*fx)(double)->double, auto (*fy)(double)->double, double a, double b,   int n = 20000)
				 ->double
{
	double s = 0.0;
	double h = (b-a)/n;
	double t = a;
	double x0 = fx(t);
	double y0 = fy(t);
	for (int i = 0; i < n; i++) {
		t += h;
		double x1 = fx(t);
		double y1 = fy(t);
		double dx = x1-x0;
		double dy = y1-y0;
		s += sqrt(dx*dx + dy*dy);
		x0 = x1;
		y0 = y1;
	};
	return s;
}

A simple C-style approach would be to define the curves we need as global functions, and if we need to parameterize the curve we will define global variables. We look at an ellipse and a cycloid. The cycloid length is easily calculated analytically. As for the ellipse, if the a and b axes are equal, it will be a circle, otherwise its length cannot be expressed by a simple formula. Below is our definition of the two curves:

//Cycloid

double cycloid_a;
auto Cycloid_fx(double t)->double {
	return cycloid_a*(1 - cos(t));
}

auto Cycloid_fy(double t)->double {
	return cycloid_a*(t - sin(t));
}

//Ellipse
double ellipse_a;
double ellipse_b;

auto Ellipse_fx(double t)->double {
	return ellipse_a*cos(t);
}

auto Ellipse_fy(double t)->double {
	return ellipse_b*sin(t);
}

Here is a sample program to calculate their sizes:

double PI = 4*atan(1.0);

ellipse_a = 1.0;
ellipse_b = 1.0;

cycloid_a = 1.0;

std::cout << std::setprecision(10) << std::setw(10);

std::cout <<  "ellipse1: " << CurveLength(Ellipse_fx, Ellipse_fy, 0.0,2*PI) << std::endl;
std::cout <<  "cycloid1: " << CurveLength(Cycloid_fx, Cycloid_fy, 0.0,2*PI) << std::endl;

ellipse_a = 3.0;
ellipse_b = 1.0;

cycloid_a = 5.0;

std::cout <<  "ellipse2: " << CurveLength(Ellipse_fx, Ellipse_fy, 0.0,2*PI) << std::endl;
std::cout <<  "cycloid2: " << CurveLength(Cycloid_fx, Cycloid_fy, 0.0,2*PI) << std::endl;

 

The program will print:

ellipse1: 6.283185281
cycloid1: 7.999999992
ellipse2: 13.36489317
cycloid2: 39.99999996

The disadvantage of this approach is that all functions and their parameters are global.

An abstract class and virtual functions

A traditional, good C++ approach is to use an abstract class and define a member function CurveLength, which uses the member functions fx(t) and fy(t):

class Curve {
public:
	virtual auto fx(double t)->double = 0;
	virtual auto fy(double t)->double = 0;

	auto CurveLength(double a, double b, int n = 20000)->double {
		double s = 0.0;
		double h = (b-a)/n;
		double t = a;
		double x0 = fx(t);
		double y0 = fy(t);
		for (int i = 0; i < n; i++) {
			t += h;
			double x1 = fx(t);
			double y1 = fy(t);
			double dx = x1-x0;
			double dy = y1-y0;
			s += sqrt(dx*dx + dy*dy);
			x0 = x1;
			y0 = y1;
		}
		return s;
	}
};

class Cycloid: public Curve {
	double m_a;
public:
	Cycloid(double a):m_a(a) {}

	virtual auto fx(double t)->double {
		return m_a*(1 - cos(t));
	}

	virtual auto fy(double t)->double {
		return m_a*(t - sin(t));
	}
};

class Ellipse: public Curve
{
	double m_a;
	double m_b;
public:
    Ellipse(double a, double b):m_a(a),m_b(b) {}

	virtual auto fx(double t)->double {
		return m_a*cos(t);
    }

	virtual auto fy(double t)->double {
		return m_b*sin(t);
	}
};

The program will look like this:

double PI = 4*atan(1.0);

Ellipse ellipse1(1.0,1.0);
Cycloid cycloid1(1.0);

std::cout << std::setprecision(10) << std::setw(10);

std::cout <<  "ellipse1: " << ellipse1.CurveLength(0.0,2*PI) << std::endl;
std::cout <<  "cycloid1: " << cycloid1.CurveLength(0.0,2*PI) << std::endl;

Ellipse ellipse2(3.0,1.0);
Cycloid cycloid2(5.0);

std::cout <<  "ellipse2: " << ellipse1.CurveLength(0.0,2*PI) << std::endl;
std::cout <<  "cycloid2: " << cycloid1.CurveLength(0.0,2*PI) << std::endl;

 

The problem is that all the curves have to be derived from the same base class, and if we want to use CurveLength in a library the class Curve should be part of it.

Using delegates

Delegates allow us to deal with unrelated classes. Here is the approach using delegates:

auto CurveLength(std::function<double(double)> fx, std::function<double(double)> fy, double a, double b, int n = 20000)->double {
	double s = 0.0;
	double h = (b-a)/n;
	double t = a;
	double x0 = fx(t);
	double y0 = fy(t);
	for (int i = 0; i < n; i++) {
		t += h;
		double x1 = fx(t);
		double y1 = fy(t);
		double dx = x1-x0;
		double dy = y1-y0;
		s += sqrt(dx*dx + dy*dy);
		x0 = x1;
		y0 = y1;
	}
	return s;
}

double PI = 4.0*atan(1.0);

class Cycloid {
	double m_a;
public:
	Cycloid(double a):m_a(a) {}

	auto fx(double t)->double {
		return m_a*(1 - cos(t));
	}

	auto fy(double t)->double {
		return m_a*(t - sin(t));
	}
};

class Ellipse {
	double m_a;
	double m_b;
public:
	Ellipse(double a, double b):m_a(a),m_b(b) {}

	auto getX(double t)->double {
		return m_a*cos(t);
	}

	auto getY(double t)->double {
		return m_b*sin(t);
	}
};

 

I have deliberately given different names to member functions. These two classes are unrelated. Here is a program:

int main() {
	Ellipse ellipse1(1.0,1.0);
	Cycloid cycloid1(1.0);

	auto ellipse1_fx = create_delegate(&ellipse1,&Ellipse::getX);
	auto ellipse1_fy = create_delegate(&ellipse1,&Ellipse::getY);
	auto cycloid1_fx = create_delegate(&cycloid1,&Cycloid::fx);
	auto cycloid1_fy = create_delegate(&cycloid1,&Cycloid::fy);

	std::cout << std::setprecision(10) << std::setw(10);

	std::cout <<  "ellipse1: " << CurveLength(ellipse1_fx, ellipse1_fy, 0.0,2*PI) << std::endl;
	std::cout <<  "cycloid1: " << CurveLength(cycloid1_fx, cycloid1_fy, 0.0,2*PI) << std::endl;

	Ellipse ellipse2(3.0,1.0);
	Cycloid cycloid2(5.0);
	auto ellipse2_fx = create_delegate(&ellipse2,&Ellipse::getX);
	auto ellipse2_fy = create_delegate(&ellipse2,&Ellipse::getY);
	auto cycloid2_fx = create_delegate(&cycloid2,&Cycloid::fx);
	auto cycloid2_fy = create_delegate(&cycloid2,&Cycloid::fy);

	std::cout <<  "ellipse2: " << CurveLength(ellipse2_fx, ellipse2_fy, 0.0,2*PI) << std::endl;
	std::cout <<  "cycloid2: " << CurveLength(cycloid2_fx, cycloid2_fy, 0.0,2*PI) << std::endl;

	return 0;
}

 

Delegates allow us to use the same functions for various curve classes, which are completely unrelated. This CurveLength can be part of the library.

An alternative approach: using lambdas

The C++11 lambdas make it possible to define functions immediately and also to capture the variables from the environment. The CurveLength and the curve classes can be defined exactly the same as in the example with delegates, but the program, the function calls change:

int main() {
	Ellipse ellipse1(1.0,1.0);
	Cycloid cycloid1(1.0);

	auto ellipse1_fx = create_delegate(&ellipse1,&Ellipse::getX);
	auto ellipse1_fy = create_delegate(&ellipse1,&Ellipse::getY);
	auto cycloid1_fx = create_delegate(&cycloid1,&Cycloid::fx);
	auto cycloid1_fy = create_delegate(&cycloid1,&Cycloid::fy);

	std::cout << std::setprecision(10) << std::setw(10);

	std::cout <<  "ellipse1: " << CurveLength(ellipse1_fx, ellipse1_fy, 0.0,2*PI) << std::endl;
	std::cout <<  "cycloid1: " << CurveLength(cycloid1_fx, cycloid1_fy, 0.0,2*PI) << std::endl;

	Ellipse ellipse2(3.0,1.0);
	Cycloid cycloid2(5.0);
	auto ellipse2_fx = create_delegate(&ellipse2,&Ellipse::getX);
	auto ellipse2_fy = create_delegate(&ellipse2,&Ellipse::getY);
	auto cycloid2_fx = create_delegate(&cycloid2,&Cycloid::fx);
	auto cycloid2_fy = create_delegate(&cycloid2,&Cycloid::fy);

	std::cout <<  "ellipse2: " << CurveLength(ellipse2_fx, ellipse2_fy, 0.0,2*PI) << std::endl;
	std::cout <<  "cycloid2: " << CurveLength(cycloid2_fx, cycloid2_fy, 0.0,2*PI) << std::endl;

	return 0;
}

I deliberately show two approaches to capture variables: a specific one [&ellipse1] , and general [&]. Either can be used. Lambdas are easy to use, but syntax becomes longer if you have to deal with more parameters. In the end, it’s your choice.

What is Assembly Programming Language?

December 3, 2015 | Article | No Comments

Assembly is considered as the oldest programming language. Learning assembly will improve our understanding or machine. In this first article of assembly tutorial we will discuss about what is assembly and why we should learn it.

What is Assembly Language?

Strictly speaking, assembly language is a programming language. It is corresponded to command / statement of computer instruction. The assembly programming is not so machine-independent language as processor has so much variation. In the next article we will cover only assembly language which refer to IBM-PC compatible’s instruction set or known as Intel x86 processor family.

Assembly language is a set of instruction specific to particular computer system. To write a assembly language we need an assembler or compiler which translate our source code to machine language. In term of programming language we won’t see human language as much as C\C++ does, but rather mnemonic for basic instruction like: mov, mul, div, add, sub, inc, etc.

Assembly language is considered as low level programming as it is the closest programming language to machine code. Because of the lack of abstraction in assembly language, assembly programming is also considered as difficult language (but don’t worry, we will discuss it).

Why Assembly Language?

There are many programming language out of there, but why we need to learn assembly? One of reason is to learn computer architecture and give deeper understanding about what is done inside. Another reason would be a certain programming language has difficulties to accessing some machine specific instructions. For a better performance, assembly can be used as it is simple and closest to machine.

Programming in assembly is not always using only assembly language. Once we can interfacing our code with other programming language. Often this method is used for creating program as assembly manages specific implementation of system while higher programming language manage the rest. To do this we need to know how higher language structure and translated into assembly (every language would)

The machine Language

A electronic-based computer only knows two type of value: 1 and 0 known as binary value. In machine language we actually instruct some CPU to utilize register or memory with a fix-size command in binary form. A machine language is built from set of number 1 and 0 and interpreted by CPU. A CPU usually has small program embedded on chip, known as microcode, which translate machine instruction to hardware signals.

As noted before, a machine language instruction is a fix-length instruction. Usually there are 16 bits for a single instruction. The first 8 bits is used for operation code, or opcode, which tell us what the instruction will do or achieve. The next 8 bits is operand.

Let’s see this example:

1011000000000101

The first 8 bits is opcode for move instruction which assign a value to specific place. The next operand tell us about location of register AL and what value would fill it.

A register is a high speed memory inside of CPU chip. It is identified in assembly language by 2 or 3 character, such as: AH, AL, CX, or EBX.

Instruction set is set of machine instruction that can be executed by machine. Intel processor family has downward compatibility which means a newer processor can understand instruction for earlier processor.

In earlier of computing, every program must be written in machine language (hence in series of 1 and 0). This is more complicated and frustrating too so people invented assembly language to ease their job.

Beginning C++: Operators

December 3, 2015 | Article | No Comments

When writing a program we are often demanded to define operations, either calculations, comparison, etc. To do it we need operators and C++ has a complete arsenal that can be used. In this article we will divide our focus into some subjects: assignment operator, unary operators, binary operators, ternary operators.

Assignment Operator

Assignment is a operator for storing a value into a variable or a constant. This operator is symbolized by equal sign (=). Let’s take a look of it in this snippet:

#include <iostream>
using namespace std;

int main() {
	// when declaring a constant we have to assign a value immediately.
	const float PHI = 3.14;

	// declaring variables
	char myChar;
	int myInt;
	double myDouble;

	// assign each variable
	myChar = 'A';
	myInt = 135;
	myDouble = 21.0378;

	// print out the value of each variable
	cout<<myChar<<endl;
	cout<<myInt<<endl;
	cout<<myDouble<<endl;
	return 0;
}

Unary Operator

An unary operator is an operator which only has one operand for the operation. These type of operator has following operators:

Operator Operations Example
+ Make a number become positive +7
Make a number become negative -7
++ Increment C++
Decrement C–

An increment is an incremental of a value on a variable by one. For example a variable C initially has value 4 and we do incrementing it then the value of C now become 5. Similar with increment, a decrement take a variable and do decremental of a value by one. Thus, when C is initially has value 4 and we do decrementing then the value of C will become 3.

There are to type of increment and decrement: pre and post. Both will have same result in the end but they are different in operation.

The pre- (either increment or decrement) would do value-changing first before being used. While in post- (either increment or decrement) the value is changed after being used.

Let’s take a look of how the concept mean:

#include <iostream>
using namespace std;

int main() {
	int x = 5;
	int y = 5;

	cout<	cout<	cout<
	x = 5;

	cout<	cout<	cout<
	cout<	cout<	cout<
	y = 5;

	cout<	cout<	cout<
	return 0;
}

Binary Operator

In mathematics, a binary operator is an operator which has two operand for its operation. In C++, we divide binary operators into smaller categories: arithmetic operators, logic operators, relational operators, and bitwise operators.

Arithmetic Operator

Arithmetic operators are operators used for computing and calculating a value from another value. Like what we have learned from school, we know there are some operators in mathematics and we have it too on C++:

Operator Operations Example
+ Addition 2 + 7 = 9
Reduction 3 – 1 = 2
* Multiplication 3 * 5 = 15
/ Division 6 / 3 = 2
% Modulo 11 % 3 = 2

You must be familiar with +, -, *, and / operator. But please note for / operator, this operator will result on integer value if both of operands are integers. So if you have a = 5 and b = 2 and do a / b, instead of 2.5 you will get 2. To get a real value, you must supply one of operand (either numerator or denominator) with real-valued number.

Some of you maybe aren’t familiar with modulo operation. In simple way, a modulo operation will give an integer for remainder of division. Let’s take example from the table. We have two number, 11 and 3. When we divide 11 with 3, resulting in 3 and has remainder 2 (number that can’t be divided by 3). The modulo operation will give value 2 as a result. Another example: 6 % 4 will give 2, 19 % 5 will give 4, etc.

Logical Operators

Logical operator is an operator used for operation in which resulting only two distinct value: true or false. It is corresponded with boolean value in previous discussion. There are three operators on this category:

Operator Operations Example
&& AND true && true = true
|| OR true || false = true
! NOT NOT false = true
&& (AND) Operator

AND operation will give true only if both of operands are true. Either from that, this operator will give false. Let’s look at this truth table:

X Y X && Y
1 1 1
1 0 0
0 1 0
0 0 0

Remember that false is represented by zero and true is represented by not-zero value.

|| (OR) Operator

OR operation will give result true if one of operands has true value. Let’s see the truth table below:

X Y X || Y
1 1 1
1 0 1
0 1 1
0 0 0
! (NOT) Operator

Value of NOT operation is an inverse of the operand. Well, actually this operator is an unary operator, but for the sake of simplicity I group it with the rest of logical operators. Let’s look at the truth table:

X ! X
1 0
0 1
Relational Operators

A relational operator is an operation to determine relation between two operands. These operators are simply comparison between two operands.

Operator Operations Example
< Less than (5 < 2) = 0
> Greater than (5 > 2) = 1
<= Less than or equal (3 <= 2) = 0
>= Greater than or equal (3 >= 2) = 1
== Equal (3 == 3) = 1
!= Not equal (3 != 3) = 0

Please note that equal operator is consists of two = symbol.

Bit-wise Operators

Unlikely other programming language, C++ support bit-wise operations. A bit-wise operations used for operation of bit manipulation. Let’s take a look for the this table.

Operator Operations Example
& AND 1 & 0 = 0
| OR 1 | 0 = 1
^ Exclusive-OR (XOR) 1 ^ 1 = 0
~ NOT ~1 = 0
<< Left Shift 5 << 1 = 10
>> Right Shift 10 >> 1 = 5

At glance you might think that these operations are similar to logical operators. Well, that’s true in some way. In bit-wise operation, the operand are every bit on both side while the logical operator use whole number as operand and both operand act only as two distinct value true or false.

Let’s take example for counterparts AND: Suppose we have two number, 5 and 2. In logical operator, both 5 and 2 are treated as true this 5 && 2 will give result true. While in bit-wise operation, we treat 5 and 2 as bits which we have 5 = 00000101 and 2 = 00000010. Then, bit-wise AND would result on:

5 00000101
2 00000010
———— &
5 & 2 00000000

Now, as you can see. We do AND operation for each bit and got result 0. With similar operation we will get 2 when we operating 6 and 2 (guess why?).

An exclusive-OR operation is bit-wise operator which similar to bit-wise OR operator. But it only gives 1 if only one operand is 1 (and other is 0). Otherwise it will give 0.

The interesting part is shifting. Shift operation, like the name, is an operation to shift the bit to a direction, The number that would be shifted is the left operand and it will be shift to x place as given by right operand. Let’s look example for left and right shift.

A left shift (a << b) will shift a to b position in left. Suppose we have two number, 5 = 00000101 and 2 and did left shift like this: 5 << 2, the bits of 5 would be shift in a way that result in 00010100 = 20. Note that the result bit is actually shifted 2 position from previous one.

A right shift (a >> b) will shift a to b position in left. Suppose we have two number, 4 = 00000100 and 2 and did the right shift like this: 4 >> 2, the bits of 4 would be shift in a way that result in 00000001 = 1. Note that the result bit is actually shift 2 position form previous one.

Ternary Operator

Ternary operator is an operator which has 3 operands for operation. It seems odd but the operator consists of 2 symbols ? and :. General scheme for this operator is given below:

expression1 ? expression2 : expression3;

This operator consist of 2 stage: checking and executing. First it will check the condition on expression1. If expression1 result in true, the expression2 will be executed. If not, the operator will execute expression3. Now let’s take a look of this snippet:

#include <iostream>
using namespace std;

int main() {
	// declare 2 variables, x with random-initialized value and y with initial value 5
	int x, y = 5;

	// check if y > 0. It would be true so we have -y as a result of this operation
	x = (y > 0) ? -y : y;

	// Let's make sure the result is same as our prediction
	cout<< x <<endl;
}

 

Beginning C++: Primitive Types and Identifiers

December 3, 2015 | Article | No Comments

What is Identifiers?

Literally, identifiers are tokens / symbols used to identify objects declared in program. Compiler knows object through identifier. Identifier can be a variable name, constants, functions, classes, template, even namespace.

In this article we will discuss identifiers in the smaller scope: variables and constants.

Identifier act as variable (or constant) is a value-container. Both of them can save some values but they are differ in the term of how they save value. A constant can save value but it can only assigned once and the value cannot be modified at runtime. While a variable can save value and the value can be modified or changed at runtime.

Let’s save it up for later and see this little analogy:

Imagine variable and constant as a bottle. We know that a bottle is a container which can contain / save something (especially liquid). Now, the bottle has many types / kinds, such as: soysauce bottle, water bottle, kerosene bottle, gas bottle, etc. Each bottle can save specific type liquid. For example a water bottle can only save water. Imagine there is a mineral-water bottle but it contains kerosene. It’s not suitable and maybe it can bring harm later (if someone think it as a plain water and drink them, you can imagine what will come next).

From the same perspective, variables and constant do so. A variables can save a value. The values can vary but the variable can only hold one specific type of value. We can only set what kind of value the bottle can hold only at declaration. A variable can be “refilled” with another value as long as the value has same data type while a constant is cannot be refilled with another value.

Primitive Data Types

As discussed, either variables or constant can save value. But they can only save value with the same type as they are declared before. The set of values of data which variable can sabe is referred as data types. There are two types of data types: a primitive data types and user-defined data types. For this article we will focus on primitive data types.

What is primitive data type? It is a built in / native data type on C++ programming language. So far, there are four primitive data types supported on C++: integer number, real number, character, boolean. Advancing to next level, we can create a new data type using these primitive data types (let say the primitive data types are the building block to build more complex one) through enumeration process, struct, and class.

Now, how can we declare a variable?

A syntax to declare a variable is as follow:

data_type variable_name;

A data_type is a data type. It can be user-defined data type or primitive data types. While the variable_name is a variable name, an identifier.

How about a constant?

Constant declaration is similiar to variable declaration, except at the declaration the constant must be initialized with some value and preceded by keyword const.

const data_type variable_name = value;

Now let’s write the actual code with variable and constant declaration

#include <iostream>
using namespace std;

int main() {
	// declaring variables
	int i;
	float f;
	char c;
	bool b;

	// declaring constants
	const int j = 10;
	const float k = 3.14;
	const char l = 'A';
	const bool m = true;

	return 0;
}

From codes above, we have four variables: an integer variable named i, a real-value variable name f, a character variable name c, a boolean variable name b. We also have four constant: an integer constant namej, a real-value constant name k, a character constant name l, a bool constant name m.

We can’t write identifier arbitrary. There are some rules to naming an identifier. Here are the rules for naming identifier:

  • Identifier can’t be chosen from C++ reserved keyword. C++ has reserved keywords such as: for, do, while, int, float, return, etc and pick them for identifier name is strictly forbidden.
  • Identifier name is case sensitive. When you say aVariable and AVARIABLE, C++ distinguish them because they have different case although they are consist of same word.
  • Identifier name must be unique. You cannot declare two variable with totally same name even if the identifier has different data type.
  • Identifier name consists of alphabet, number, or underscore. Any character beside that is considered as invalid name. No symbolic character such as: #, @, ?, !, $, as identifier.
  • Identifier name cannot be preceded by number. Identifier can only preceded by underscore (_) and alphabets. Number can be used as identifier name, but it cannot be placed as first character.
  • Identifier cannot has space.

The Identifier Scope

The lifetime of an identifier, or in some terms the scope where an identifier can be resolved. There are two scope: global and local. This is applied to both variables and constants.

A global variable or constant, is a variable or constant declared outside of any blocks of code. Simply we can say a global variable is placed outside of any function. A global identifier is recognized in whole source code.

A Local variable or constant, is a variable or constant declared inside of a block of code. Simply we can say a local variable is place inside of a function, branching code, looping code, etc. This identifier is recognized only at declared blocks.

Outside from two identifier types, a variable can also be classified as static variable. A static variable is a variable which occupy computer memory permanently (until the program is unloaded). It means the last variable value will be kept. To declare a static variable we can write as:

static data_type identifier_name;

Similiar to normal variable, static variable can be categorized as local-static variable and global-static variable.

Another variable type we have are register variable. A register variable will be stored on CPU register. Register variable provide faster way to store a value. No need to access memory. To declare a register variable, one must do:

register data_type variable_name;

More into Data Types

We have discussed a little thing about data type at above. Now Let’s dive deeper into data types. As stated before, C++ has four built-in primitive data types: integer number, real number, character, boolean. We will cover each category. We will refer to x86 machine.

Integer Numbers

Integer numbers, as hinted by the name, is a set of number of integers. An integer is a whole number (not a fractional number) that can be positive, negative, or zero. Data types for this category are:

Data Type Size (bits) Range
int 16 or 32 -32,768 to -32,767 or
-2,147,483,648, to 2,147,483,647
unsigned int 16 or 32 0 to 65,535 or
0 to 4,294,967,295
signed int 16 or 32 similiar to int
short int 16 -32,768 to 32,767
unsigned short int 16 0 to 65,535
signed short int 16 similiar to short int
long int 32 -2,147,483,648, to 2,147,483,647
signed long int 32 similiar to long int
unsigned long int 32 0 to 4,294,967,295

Real Numbers

Real numbers are number for real-value number. Data types for this category are:

Data Type Size (bits) Range Precision
float 32 1.2E-38 to 3.4E+38 6 digits
double 64 2.3E-308 to 1.7E+308 15 digits
long double 80 3.4E-4932 to 1.1E+4932 19 digits

Character (and string)

Character are data type used for representing a character on computer. Character is based on ASCII. Inside a computer, a character is stored as number representation but it would be presented as a character. A series of character can form a string. A string is defined as sequence of characters and terminated by NULL character. This category has following data types:

Data Type Size (bits) Range
char 8 -128 to 127 or 0 to 255
unsigned char 8 0 to 255
signed char 8 -128 to 127

A string in other hand is formed by series of character. For example, if a single character is ‘A’, a string can be something like “Hello world” or “Learning C++ with Xathrya”.

Boolean

Often said as logic data type. It has only one data type, bool which has 2 different value: false (can be represented as 0) and true (can be represented as any number except 0). This data type mainly represent condition of comparison either by operator equality, inequality, greater, less.

Advanced C++: Namespace

December 3, 2015 | Article | No Comments

Let’s imagine a computer without directory nor subdirectory. Any single file would be stored on a single repository / warehouse only. What could it be? Many problems? Absolutely. Because there is only one place to keep file, any single file must have unique filename and unique identity. Another problem occurred when we want to find a file. Searching a file in set of thousand files, isn’t it frustrating?

With directory system (hierarchically), we are helped to organize our files into smaller modules. We can group files with same objectives / functions (for example: videos, accounting report, etc) into single directory.

The same objective goes to namespace. Namespace is C++ mechanism to group a set of file into some “folder” called namespace. With namespace we can prevent conflict of reduplication variable name, constant name, function name, and class name. A different system can still shared same name but they would be separated into different namespace.

Namespace is very useful for large program with high complexity. It means a program can be broken down and reorganize into different namespace.

Our popular namespace would be std. It is a namespace used by C++ standard library to group it’s functions, modules, and classes.

Let say we have two library, A and B. Without namespace, we can’t create two functions with same name (signature). But with namespace, both can use a same name.

Defining a Namespace

To define a namespace, we can use C++ keyword namespace.

namespace namespace_name {
	// declarations
}

As we can see, a namespace is a simply block / scope of code where every variable, constants, functions, and classes declared can only be known by member of namespace (inside only). When we called any member of namespace scope from outside, we need to write the name of namespace with scope-resolution operator (::). Here’s the example:

#include <iostream>
using namespace std;
int x;

// Defining namespace A
namespace A {
	// declare a variable
	int x = 10;

	// declare a function prototype print() inside namespace A
	void print();
}

// We implement our prototype inside namespace A
void A::print() {
	// x here is know by print() because we have introduce our function
	// print() as a member of namespace A
	cout<<"The value of x "<<x<<endl;
}

int main() {
	x = 10;
	print();
}

The codes above has tell us about how to declare variables and functions under namespace A. Now write, compile, and run the code. What is the value of x?

There are two x’s. One is x inside namespace A, the one that recognized by function print(). The other one is global variable x which is known by function main(). Where a function print() is called, it only know variable x inside the namespace namespace which make it call only. While the function main() only know variable x as global variable (the one inside namespace isn’t visible to main()). So that’s why, you would encounter either 0 or random value.

Two namespace? Let’s see the example:

namespace A {
	int x;
	void printx();
}
void A::printx() {
	cout<<"X inside namespace is "<<;x<<endl;
}
namespace B {
	int x;
	class Example {
	private:
		int number;
	public:
		void setNumber(int value) {
			number = value;
		}
		int getNumber() {
			return number;
		}
	};

	void printx() {
		cout<<"Now we have "<<x<<endl;
	}
}
int main() {
	A::printx();		// print x value inside namespace A
	A::Example ex;		// declaration of class Example

}

Using namespace

After defining a namespace, we must know how to use it inside of program. In other word we must know how to access variables, constants, functions, or even classes declared inside of namespace. To do so, there are two different approach: Scope resolution (::), keyword using.

Using scope resolution

To recall variable, constant, functions, or classes defined inside a namespace we can use operator :: (scope resolution).

namespace_name::member

Here’s the example of scope resolution usage:

#include <iostream>
using namespace std;

namespace A {
	int x;
	void setX(int value) {
		x = value;
	}
	int getX() {
		return x;
	}
}
int main() {
	// assign number to variable x outside of namespace A
	A::x = 10;
	cout<<"X has value: "<<A::x<<endl;

	// Call function setx() outside of namespace A
	A::setX(135);

	// call function getX() outside of namespace A
	cout<<X has value: "<<A::getX()<<endl;

	return 0;
}

Write, compile, and run. What’s the result?

Using keyword using.

First, let’s observe this code:

#include <iostream>

int main() {
	int number;
	std::cout<<"Input an integer: ";
	std::cin>>number;
	std::cout<<"You just entered number "<<number<<std::endl;

	return 0;
}

On codes above, we’re not giving using namespace std; like we always did. But we can still use cin, cout, and endl like we always did by giving std:: in front of them. That is, std is a namespace and to use member inside namespace std we use using namespace std clause. In general, to use whole namespace we can declare:

using namespace namespace_name;

But is there another way? Suppose we want to use std::cout only and the other is irrelevant (we do not use them). Can we just skip the others? Yes we can. In that case we are using only a single namespace member. Thus we declare something like this:

using std::cout;

In general we can use a member of namespace as:

using namespace_name::member;

Alias Namespace

If we are encounter a namespace has too long name to remember (or complicated name), we can rename it to different name. C++ help us to reduce the complexity by renaming old namespace into new space. This feature is called aliasing, or referring a new namespace to old namespace.

Here’s how you could do that:

namespace new_alias_name = old_namespace_name;

For instance, you want to rename a namespace a_very_long_namespace_to_write to be simple_namespace we can write:

namespace simple_namespace = a_very_long_namespace_to_write;

Nested Namespace

Inside namespace can be defined another namespace. This feature is called nested namespace and allow us to create namespace inside another namespace. C++ gives us capability to achieve high modularity, even for namespace.

A simple code for explaining nested namespace would be:

#include <iostream>
using namespace std;

// declaring nested namespace
namespace outer {
	int i;
	namespace inner {
		int j;
	}
}

// recall the namespace
int main() {
	// assign value of i and j
	outer::i = 10;		// correct
	// outer::j = 20; 	// wrong
	outer::inner::j = 20;	// correct

	cout<<"The value of i is"<<outer::i<<endl;
	cout<<"The value of j is"<<outer::inner::j<<endl;

	// using outer namespace name
	using namespace outer;
	i = 30;			// correct
	// j = 40;		// wrong
	inner::j = 40;		// correct

	cout<<"The value of i is"<<i<<endl;
	cout<<"The value of j is"<<inner::j<<endl;

	// using inner namespace name
	using namespace inner;
	i = 50;			// correct
	j = 60;			// correct

	cout<<"The value of i is"<<i<<endl;
	cout<<"The value of j is"<<j<<endl;

	return 0;
}

 

Now, what’s your comment?

Advanced C++: Mutable Member

December 3, 2015 | Article | No Comments

In the previous article we have discussed a const member function. A const member function is a mechanism for function to prevent it to modify a data.

In practical, const functions is needed to keep purity of class. A non privileged function is restricted to modify member variable. But sometimes we are forced to change data from const function (well, it’s so rare). To do so, we have to declare data as mutable member.

This simple code will tell us about keyword mutable:

#include <iostream>
using namespace std;

class Example {
	mutable int x;
public:
	void setX(int value) const {
		x = value;		// correct
	}
	int getX() const {
		return x;		// correct
	}
};

int main() {
	Example* p;

	p = new Example;
	p->setX(3);
	cout<<"The x has value "<<p->x<<endl;

	return 0;
}

In this example, function setX() is allowed to modify x because x is declared as mutable.

Advanced C++: Const Member-Function

November 24, 2015 | Article | 1 Comment

On C++, there is a way to declare a function inside a class (class’ method) as a constant function. If that is the case, the this pointer would be treated as constant pointer. Thus the function is restricted to modify any data inside its body.

To declare a function as a constant function, we must give a keyword const after the function header.

A simple code to give a hint for const member function:

#include <iostream>
using namespace std;

class Example {
int x;
public:
void setX(int value) const {
	x = value;        // wrong! Const functions are restricted
			  // to modify the data.
}
int getX() const {
	return x;        // correct!
}
};

int main() {
	Example* p;
	p = new Example;

	p->setX(3);
	cout<getX()<<endl;

	delete p;
	return 0;
}

Write and compile. Did you make it? You should get error if you write the code as is. The problem lies on function void setX(int value) const; Remember that a const function is restricted to modify the member variable, but a int getX() const; is still have read access to member variable.

Sometimes we need to change member variable by const function. To do this, member variable must be declared as mutable.

Maybe, template is one of C++ key feature that is rarely owned by other programming language. This feature is already supported by all modern / standard C++ compilers. Using template, we can create a single generic function or generic class. Simply we can create one general function or general class and whenever a similiar function or class is met, we can instance it with those problems.

Template is defined using C++ keyword, template.

Template is also the fundamental / the basis for creation of Standard Template Library (STL). STL is a collection of function or data structure that can be used for any data type. Yes, you can create a list of integer, a queue of float, a stack of string, etc with single class.

Function Template

Function template is a generic function. You create a function that does the job and every data can be passed to it, without recode the function.

Function Template with Generic Type

To create a function template, we did the same thing as creating a simple function. The difference lies on parameter type.

Here is the generic function template declaration.

template <class T>
return_type function_name( parameter1, parameter2, ...) {
	statements;
}

The template keyword describe that this function is generic function. While T on <class T> is called as generic type. It is a placeholder. This type then will be used as parameter declaration of that function. Let’s see a simple example:

#include <iostream>
using namespace std;

template
void SwapVariable(T& x, T& y) {
	T z;

	z = x;
	x = y;
	y = z;
}

int main() {
	int a = 10, b = 15;
	float c = 3.14, d = 1.15;

	SwapVariable(a,b);
	SwapVariable(c,d);

	cout<<a<<' '<<b<<endl;
	cout<<c<<' '<<d<<endl;
	return 0;
}

Write, compile, and run the above code. What are the output?

If you observe carefully, you can see that we only define one function SwapVariable but we use if for 2 different data type: int and float. This is the power of generic function.

Function Template with Two or More Generic type

When you see the declaration, the data type used for the argument are T. This indicated that both argument HAVE the same data type, regardless what type. How can we specify two or more different data type?

template <class T, class U>
void Writeln(T x, U y) {
	cout<<x<<' '<<y<<endl;
}

The above code is a generic function with two different generic type, T and U respectively. Those T and U can be replaced with any other type, such as: int, float, char, etc. Interesting, huh? 😀

In general, the generic types are declared inside template< >. If you want three you should declare three inside them. How about four?

template<class TYPE1, class TYPE2, class TYPE3, class TYPE4>
void aFunction(TYPE1 w, TYPE2 x, TYPE3 y, TYPE4 z) {
	// do somethings
}

Function Template Overload

Just like ordinary function, function template can be overloaded. This code will give you a hint to do so:

#include
using namespace std;

template<class TYPE1>
void writeIt(TYPE1 x) {
	cout<<x<<endl;
}

template<class TYPE1, class TYPE2>
void writeIt(TYPE1 x, TYPE2 y) {
	cout<<x<<endl;
	cout<<y<<endl;
}

int main() {
	writeIt(3);
	writeIt(1, 2.5);

	return 0;
}

See? We have overloaded writeIt function for our need.

Generally speaking, function template is used if we have generic algorithm and can be used to similiar data type. Later, the compiler will create a specific instance of function for given data type. It is done in compiler level, you just need to write once.

Class Template

Besides function template, C++ also provide Class Template. Similiar to function template. class template can be used to create generic class for any similiar functional of different type of class.

Class Template with One Generic Type

In principle, defining class template is similiar to defining ordinary class. Here is a generic class template declaration:

template <class T>
class class_name {
access specifier:
	data
	methods
};

To instantiate a class template, we have general statement like this:

class_name < data_type > instance_name;

Now let see the simple example:

#include <iostream>
using namespace std;

template<class T>
class EXAMPLE {
public:
	EXAMPLE(T xx) { x = xx; }
	void showOff() { cout<<x<
private:
	T x;
};

int main() {
	EXAMPLE<int>  A(10);
	EXAMPLE<string>  B("Xathrya Sabertooth");
	EXAMPLE<float>  C(3.14);
	EXAMPLE<char>  D('A');

	A.showOff();
	B.showOff();
	C.showOff();
	D.showOff();

	return 0;
}

compile and see the result.

Here in our example, we have EXAMPLE class with one generic type. The EXAMPLE class then can be instantiate to different object with different characteristic, A with int, B with string, C with float, D with character. Everything from a same class.

Class Template with Two or More Generic Type

Similiar to generic function declaration, a class template definition can be composed of two or more generic type. Here is a sample code of it:

#include <iostream>
using namespace std;

template<class TYPE1, class TYPE2>
class EXAMPLE {
	TYPE1 x;
	TYPE2 y;

public:
	EXAMPLE(TYPE1 xx, TYPE2 yy) {
		x = xx;
		y = yy;
	}
	void showOff() {
		cout<<x<<' '<<y<<endl;
	}
};

int main() {
	EXAMPLE<int, float>  A(15, 4.67);
	EXAMPLE<string, int>  B("Xathrya",30);

	A.showOff();
	B.showOff();
}

Write, compile, and run the code. What is the result? 😀

Template with typename keyword

In previous example we always use keyword class to define a generic type. There is another way to define a generic type, using typename class. Essentially, the declaration by class and declaration by typename is interchangable. So these declaration for function template is equivalence:

template<class T>
void function1(T t);

template<typename T>
void function2(T t);

So let’s summarize this article. What is the benefit using template?

  • Save up time: why would you write “same” code everytime? Write once for similiar condition. Besides, you can read and write fewer code 😀
  • Can be used for another situation: function and class template can be used for any data type.
  • Improving program flexibility

Beginning C++: Comments Style Guide

November 24, 2015 | Article | No Comments

Comments, believed or not, is one of important concept. It is not as crucial as logic flow in program but comment is still believed as one.

Comments are portions of the code ignored by the compiler which allow programmer to make simple notes in the relevant areas of the source code. Comments come either in block form or as single lines. It is simply ignored by compiler. But the value of comment lies as a note, a message between programmer, a reminder about piece of code, etc.

A good comment can prevent miscommunication between programmers. How can you explain your piece of code? A comment would do.

Why do I have to write a single article for just a comment? Here, in this article I want to give you a good way of writing and code. Isn’t it nice if other people can understand your code without you explain face to face by them, only by comments?. See the essential point there? Great!

Type of comments on C++

How could you write a comment on C++? There are two kinds / types: single-line and multi-line comments.

Single-line comment

A single line comment is a comment accommodated only on single line. It is start with // and continue untul the end of the line (met newline character). If the last character in a comment line is a \ the comment will be coninued in the next line.

sample:

// This is a single comment. The code below will be compiled.
void myFunction();

// This is a comment \
written in some lines. The code written below will be compiled.
void myFunction2();

void myFunction3(); // The code will be compiled, except this comment

Multi-line comment

A block of comment is consist of one to many comment at a single area. Start with /* and end with */. If you enclose code within it, the code would be part of comment. It won’t be compiled by compiler. remember to CLOSE the comment block you have start.

Sample:

/*
This is a comment
in a block
Expect it
*/
void myFunction();

/*
void myFunction2();
That function won't be compiled.
*/

void myFunction3(); /* this code would be compiled */

When and How to Comments

We have known the 2 comment types on C++. Now let’s inspect how can we use the comment? These are some nice style of commenting. I won’t force you to follow it.

  1. Write comment above or below a function to describe what it does and other characteristic (parameter / argument needed, return value, etc)
  2. If you write struct or class, write a member variable in a single line and give comment of what is it.
  3. a

There is a nice example about how we write a comment:

// This structure store value for computer register
struct Register {
int h; // This is the high bit
int l; // This is the low bit
};

/**
 * @author: Satria Ady Pradana
 *
 * Create a vector dynamically using heap allocation.
 * @pre
 *      V is not initialize
 *      size is defined and has value > 0
 *
 * @post
 *      V is created with size nodes
 *
 * @param
 *      V: a pointer
 *      size: size of list we want to create
 *
 * @return
 *      <none>
 *
 * @throw
 *     <none>
 */
void createVector(Pointer& V, int size);

A nice and sweet piece of code, right? 😀
The code is self explained with explanation for each stage. Each parameter is also documented.

Social Share Buttons and Icons powered by Ultimatelysocial