プログラミング

C++ Template Metaprogramming

Posted on Updated on

From my last entry I ended up writing this program while studying Template Metaprogramming:

#include <iostream>

template <int N> struct Factorial {
	static const int result = N * Factorial<N-1>::result;	
};

// describes a specific case of a Factorial
// We need a base case (a way to break out of the recursive loop, which in this case
// is 1)
template <> struct Factorial<0> {
	static const int result = 1;	
};


template <int N, int D> struct Frak {
	static const long Num = N;
	static const long Den = D;
};

template <int N, typename F> struct ScalarMultiplication {
	typedef Frak<N*F::Num, F::Den> result;	
};

int main() {
	typedef Frak<2, 3> Two_Thirds;
	
	typedef ScalarMultiplication<2, Two_Thirds>::result Four_Thirds;
	std::cout << Four_Thirds::Num << "/" << Four_Thirds::Den << "\n";
	return 0;
}

This looks messy but I finally figured out why the executed result is 4/3, and the reason is pretty simple but hard to notice.

Starting from Main():

int main() {
	typedef Frak<2, 3> Two_Thirds;
	
	typedef ScalarMultiplication<2, Two_Thirds>::result Four_Thirds;
	std::cout << Four_Thirds::Num << "/" << Four_Thirds::Den << "\n";
	return 0;
}

Two_Thirds is a variable type and its a method call to Frak, which is a blue print to when we call our ScalarMultiplication template.

template <int N, int D> struct Frak {
	static const long Num = N;
	static const long Den = D;
};
template <int N, typename F> struct ScalarMultiplication {
	typedef Frak<N*F::Num, F::Den> result;	
};

// somewhere in Main() ...
int main() {
         // ///	
	typedef ScalarMultiplication<2, Two_Thirds>::result Four_Thirds;
        // ...
}

N is 2, and F is 3. But looking closely at this line:

typedef Frak<N*F::Num, F::Den> result;	

Our template takes 2 parameters. 2 and 3, and the first parameter is 2 … which is then multiplied by itself to the number 4 and 3 is never calculated. So later when we print the results of this code we will get the answer 4/3

Hopefully if anybody was confused they might find this a little bit clearer … I hope…

EDIT: 2015/04/28
Thanks to nicolasbrailo for clearing up the confusion I had (my bad (d’oh!)) about Two_thirds. It’s not a variable, its a type. Check out his comment below for more details. Thanks bro! ^^
My code after modified according to Nicolas’s comment:

#include <iostream>
 
struct Two_thirds {
    static const long Num = 2;
    static const long Den = 3;
};

int main() {
    std::cout << (Two_thirds::Num*Two_thirds::Num) << "/" << Two_thirds::Den << "\n";
    return 0;
}

Much easier!

Advertisements

Pointers in C++

Posted on Updated on

Following my last entry I decided to take another look at C++ pointers, pointer by reference and pointer by value (It’s still confusing for me so I did this to see if it makes telling the two apart any easier):

#include "pointer_test.h"d
#include <iostream>
 
using namespace std;
 
pointer_test::pointer_test() {
  // constructor
}
 
pointer_test::~pointer_test() {
  // destructor
}
 
int main() {
  int var = 20;
  int *ip;    // pointer reference
 
  ip = &var;
 
  cout << "&var -- " << &var << "\n"; // 0x7fff5b73c828, pointer by value
  cout << "var -- " << var << "\n"; // 20, pointer by reference
 
  cout << "&ip -- " << &ip << "\n"; // 0x7fff5b73c828, pointer by value
  cout << "*ip -- " << *ip << "\n"; // 20, pointer by reference
 
  return 0;
}

Also got a haircut on Sunday in Tenjin. First time going to a Japanese salon and I must say for the price I paid (4000-ish yen) I quite like it. At first I would think paying to get a haircut is stupid if I can do it myself but looking this stylish feels refreshing!

Playing with C++ – Initialization Lists (Quadratic Equation solver source)

Posted on Updated on

Wanted to post this on Monday but I kept getting a weird error on WordPress.
Last year while I worked on a different project using C++ I came across something I had never seen before in C++ called Initialization Lists. It was also the same time that I realized knowing very little about this technology while assuming it is the same as C# is a bad idea.

In my previous project I had stumbled upon a piece of code in a C++ constructor like this:

/*
 * コンストラクタ
 */
ClassName::ClassNameConstructor()
:_int_a()
,_vector_list()
,_bool_init_state()
{

}

What caught my attention first was the colon symbol before what looked like method calls. This is wrong. It’s much easier if you look at the above code like this (for me .. at least):

/*
 * コンストラクタ
 */
ClassName::ClassNameConstructor() :_int_a() ,_vector_list() ,_bool_init_state()
{

}

All this does is initialize our variables in our header file to a value (just in case) and then we can just override their values to anything we want later. I used this example in my quadratic equation solving program like so:

Header file:

// #include "firstSolution.h"
#ifndef _FIRST_SOLUTION_H
#define _FIRST_SOLUTION_H

class firstSolution {
private:
	// 係数
	int a_value;
	int b_value;
	int c_value;

	// 二次方程式
	double quadratic_formula;

protected:
	double result[2];

public:
	firstSolution();   // コンストラクタ
	~firstSolution();  // デストラクタ

	void enterValues();
	void getValues();

	template<typename T> // は?
	T calculateAC(T a, T c);

	template<typename T> // は?
	T calculateTwoA(T a, T two);	
	
	void calculateSquareRoot(int a, int b, int c);
};

#endif // _FIRST_SOLUTION_H

Implementation file:

// rest of the code goes here
firstSolution::firstSolution()
    : a_value(0)
    , b_value(0)
    , c_value(0)
    , quadratic_formula(0)
{
	// 一応これも初期化する(上)
	// コンストラクタ
}
// rest of the code goes here

And all this is, is a different way of writing our constructor like below (dont know if this compiles, just an example):

firstSolution::firstSolution() {
    a_value = 0
    b_value = 0
    c_value = 0
    quadratic_formula = 0
}

Full source of the implementation file:

#include "firstSolution.h"
#include <math.h>
#include <iostream>

using namespace std;

firstSolution::firstSolution()
    : a_value(0)
    , b_value(0)
    , c_value(0)
    , quadratic_formula(0)
{
	// 一応これも初期化する(上)
	// コンストラクタ
}

firstSolution::~firstSolution() {
	// デストラクタ 
}

/*
 * a、b、cの値を取得
 */
void firstSolution::enterValues() {
	cout << "初期化 a = " << a_value << "\n";
	cout << "初期化 b = " << b_value << "\n";
	cout << "初期化 c = " << c_value << "\n";

	// とりあえずこれでいける...
	cout << "二次方程式:ax2 + bx + c = 0" << "\n" << "ax2 + bx - c = 0 の場合は" <<
			"cをマイナス数字で入力してください\n";

	cout << "aの値を入力してください: " << "\n";
	cin >> a_value;

	cout << "bの値を入力してください: " << "\n";
	cin >> b_value;

	cout << "cの値を入力してください: " << "\n";
	cin >> c_value;

	cout << "aの値を [ " <<  a_value << " ]として入力されました。\n";
	cout << "bの値を [ " <<  b_value << " ]として入力されました。\n";
	cout << "cの値を [ " <<  c_value << " ]として入力されました。\n";

	this->calculateSquareRoot(a_value, b_value, c_value);
}

/*
 * 4*(a*c)
 * 入力されたデータは一般化されたのでdoubleかintでも計算できる
 */
template<typename T>
T firstSolution::calculateAC(T a, T c) {
	return a*c;
}

/*
 * 2*a
 * 入力されたデータは一般化されたのでdoubleかintでも計算できる
 */
template<typename T>
T firstSolution::calculateTwoA(T a, T two) {
	return a*two;
}

/*
 * 平方根の計算
 */
void firstSolution::calculateSquareRoot(int a, int b, int c) {
	double ac = this->calculateAC(a, c);
	double atwo = this->calculateTwoA(a, 2);

	quadratic_formula = sqrt((b*b) - (4 * ac));				// ax2 + bx + c = 0
	result[0] = (((b * -1) + quadratic_formula) / atwo);	// 二次方程式(+)
	result[1] = (((b * -1) - quadratic_formula) / atwo);    // 二次方程式(ー)
}

/*
 * 処理された回答を取得
 */
void firstSolution::getValues() {
	cout << "結果 ===========================================" << "\n";
	cout << "b*b = " << b_value*b_value << "\n";
	cout << "ac = " << a_value*c_value << "\n";
	cout << "quadratic_formula = " << quadratic_formula << "\n";
	cout << "quadratic_formula / 2 = " << quadratic_formula / 2<< "\n";

	// 結果
	for(int i = 0; i < 2; i++) {
		cout << "x = [ " <<  result[i] << " ]\n";
	}
}

/*
 *  ax2 * bx + c = 0 は実際にax2 * bx - c = 0になっているか後に判定処理を書く。
 */
int main () {
	firstSolution fs;

	fs.enterValues();
	fs.getValues();
	return 0;
}

Compiling this will print:

benjamin.lo% g++ firstSolution.cpp
benjamin.lo% ./a.out
初期化 a = 0
初期化 b = 0
初期化 c = 0
二次方程式:ax2 + bx + c = 0
ax2 + bx – c = 0 の場合はcをマイナス数字で入力してください
aの値を入力してください:
1
bの値を入力してください:
3
cの値を入力してください:
-4
aの値を [ 1 ]として入力されました。
bの値を [ 3 ]として入力されました。
cの値を [ -4 ]として入力されました。
結果 ===========================================
b*b = 9
ac = -4
quadratic_formula = 5
quadratic_formula / 2 = 2.5
x = [ 1 ]
x = [ -4 ]

Notice that in the terminal we have:

初期化 a = 0
初期化 b = 0
初期化 c = 0

This is a printed result from our enterValues() method which prints the initial values of a_value, b_value, c_value before the user enters their own values for calculation.

Playing with C++ – Pointers

Posted on Updated on

I dreaded pointers for a very long time and still kind of do because of how tricky they are to understand. For practice, I wrote the program below (based from this tutorial http://www.tutorialspoint.com/cplusplus/cpp_pointers.htm):

#include <iostream>

using namespace std;

pointer_test::pointer_test() {
	// constructor
}

pointer_test::~pointer_test() {
	// destructor
}

int main() {
	int var = 20;	// pointer value
	int *ip;		// pointer reference

	ip = &var;

	cout << "Value of var variable: " << var << "\n";
	cout << "value of ip (pointer by reference): " << *ip << "\n";
	cout << "ip (pointer by reference): " << ip << "\n";

	return 0;
}

When executed:

900586-m@benjamin.lo% g++ pointer_test.cpp
900586-m@benjamin.lo% ./a.out
Value of var variable: 20
value of ip (pointer by reference): 20
ip (pointer by reference): 0x7fff4ff65828

What I now understand is that:

– &var will point to the value of what the pointer has as its value.
– ip will also point to the value of what the pointer has as its value (same as above), but, ip’s value is not really defined but is actually referencing to the var pointer’s value.

– *ip will assign its memory address as its value (which is the address of var’s value)

Cool, Hopefully this was easy enough for me to remember later.