2011年07月22日

C/C++で多次元配列を引数に取るには

C言語学習時、確かに勉強した記憶があるんだが書き方忘れた。で、詰まった。
備忘録代わりにメモメモ。

int array[2][3];

なんて配列があって、これを引数に取る関数は、以下のようになる。

/* [x][3]な二次元配列を取る関数 */
int function(int arg[][3]);
int function(int (*arg)[3]);	// これでもおk

n次元配列の、右から数えてn-1次元目までは要素数を書かなければならない。
つまり、

/* [x][4][5]な三次元配列を取る関数 */
int function3(int arg[][4][5]);
/* [x][6][7][8]な三次元配列を取る関数 */
int function4(int arg[][6][7][8]);

ただし、

/* 1次元目も2次元目も何が来ても問題なく処理出来る関数……のつもり */
int functionX(int arg[][]);

みたいな真似は不可。
まぁ、C/C++の配列の仕様(添字が範囲外の値かどうかチェックしない)を考えると、この制限も納得なんだけど。

C++だとtemplate使えば上で挙げたような真似は一応出来る。

template<std::size_t N> int function(int arg[][N]);
int a[2][3], b[4][5];	// aとbの添字の数値が異なる点に注目
function(a);
function(b);

まぁこれで何が嬉しいかというと、例えばchar[][]から任意文字列を探すstd::find()の特殊化が出来るよね、とか。

次回に微妙に続く。

ラベル:C C++
posted by 天井冴太 at 01:44| Comment(0) | TrackBack(2) | Study | 更新情報をチェックする

2011年05月22日

型の擬似的な上書き ――BOOST_AUTO_TEST_CASE_FIXTUREの仕組みより――

個人的に目から鱗だったのでメモ。

Boost.Testsetup/teardown的な物を書くにはどうすれば良いのかなーとググって、IT戦記のコメント欄経由でBOOST_FIXTURE_TEST_SUITE()の存在を知る。
で、ふと該当部分のコードがどうなってるのか気になったので覗いてみた。

以下引用コードは全てBoost 1.45.0のunit_test_suite.hppから。

#define BOOST_FIXTURE_TEST_SUITE( suite_name, F )					   \
BOOST_AUTO_TEST_SUITE( suite_name )									 \
typedef F BOOST_AUTO_TEST_CASE_FIXTURE;								 \
/**/

53~56行、BOOST_FIXTURE_TEST_SUITE()マクロの定義部分。このマクロの第2引数に指定したクラスがfixture実装クラスとなり、コンストラクタがsetup処理、デストラクタがteardown処理になる。利用法は上に挙げたメモの日々(2009-05-26)を参照。

さて、このコードを見ると、fixtureを使わない場合に使用するBOOST_AUTO_TEST_SUITE()を内部で利用している。BOOST_AUTO_TEST_SUITE()は44~47行にて定義されており、次のようになっている。

#define BOOST_AUTO_TEST_SUITE( suite_name )							 \
namespace suite_name {												  \
BOOST_AUTO_TU_REGISTRAR( suite_name )( BOOST_STRINGIZE( suite_name ) ); \
/**/

で、実際のテストケースを記述するBOOST_AUTO_TEST_CASE()マクロは次のように定義されている。114~116行。

#define BOOST_AUTO_TEST_CASE( test_name )							   \
BOOST_FIXTURE_TEST_CASE( test_name, BOOST_AUTO_TEST_CASE_FIXTURE )
/**/

BOOST_FIXTURE_TEST_SUITE()の定義内にてtypedefされているBOOST_AUTO_TEST_CASE_FIXTUREが此処で利用されている。
……あれ?でもこれってBOOST_AUTO_TEST_SUITE()利用時には定義されていない筈だよな?一体どうなってるんだろう?

"BOOST_AUTO_TEST_CASE_FIXTURE"でコード内を検索すると、以下の記述が見つかる。193~202行。

namespace boost { namespace unit_test { namespace ut_detail {

struct nil_t {};

} // namespace ut_detail
} // unit_test
} // namespace boost

// Intentionally is in global namespace, so that FIXURE_TEST_SUITE can reset it in user code.
typedef ::boost::unit_test::ut_detail::nil_t BOOST_AUTO_TEST_CASE_FIXTURE;

グローバルスコープにて全く同じ名前の型がtypedefされている。

つまり、BOOST_AUTO_TEST_SUITE()使用時は、

typedef ::boost::unit_test::ut_detail::nil_t BOOST_AUTO_TEST_CASE_FIXTURE;

namespace test_suite_name {
// 略
BOOST_FIXTURE_TEST_CASE(test_case_name, BOOST_AUTO_TEST_CASE_FIXTURE); // グローバルの物が使われる
// 略

……のように展開され、グローバルスコープに定義されたBOOST_AUTO_TEST_CASE_FIXTUREが利用される。

が、対してBOOST_FIXTURE_TEST_SUITE()使用時は、

typedef ::boost::unit_test::ut_detail::nil_t BOOST_AUTO_TEST_CASE_FIXTURE;

namespace test_suite_name {
typedef fixture_class_name BOOST_AUTO_TEST_CASE_FIXTURE;
// 略
BOOST_FIXTURE_TEST_CASE(test_case_name, BOOST_AUTO_TEST_CASE_FIXTURE); // 同じ名前空間内の物が使われる
// 略

……のように展開され、名前空間内のtypedefに因ってグローバルスコープのBOOST_AUTO_TEST_CASE_FIXTUREが隠蔽されるようになっているのである。

確かに、このような場合には、より内側の物で外側が隠蔽されると入門書で読んだ記憶があるが、実際に使われているコードを見るのは初めてかも。

目から鱗というか、盲点だったというか。

setup/teardown
それぞれ、テスト開始時に必ず行う処理、テスト終了時に必ず行う処理
Boost 1.45.0
2011年5月22日現在、最新のバージョンは1.46.1だが、ものぐさこいてアップデートしてなかった……
ラベル:C++ boost Boost.Test
posted by 天井冴太 at 04:05| Comment(0) | TrackBack(0) | Hack | 更新情報をチェックする

2011年05月14日

Visual C++ 2010で生じる、warning C4819を退治する

何らかの理由によりVC++のエディタ画面以外でコードを編集したいと言う事はよく有る。そういった時、いざVC++でコンパイルしようとした時に警告が発生する事がある。

例えば以下のようなコードを何らかのテキストエディタで記述し、UTF-8で保存する。

#include <iostream>
using namespace std;

int main()
{
	cout << "このプログラムには日本語の文字列が含まれています。" << endl;
}

で、これをコンパイルすると、以下のような警告/エラーが発生する事が有る。

test.cpp : warning C4819: ファイルは、現在のコード ページ (932) で表示できない文字を含んでいます。データの損失を防ぐために、ファイルを Unicode 形式で保存してください。
test.cpp(6) : error C2001: 定数が 2 行目に続いています。
test.cpp(7) : error C2143: 構文エラー : ';' が '}' の前にありません。

しかし、全く同じコードをVC++IDEにて作成した場合はエラーとならない。

何故か。

どうやら、VC++UTF-8なソースコードをコンパイルしようと思ったら、BOMが必要となるらしい。
エラーメッセージの現在のコード ページ (932)という記述から推察するに、BOMが無ければCP932として処理しているのだろう。

IDE上で文字化けする訳でもないのに、不思議な話である。

[VC++ 2010にてファイルの文字コードを変更するには、"ファイル"メニューの"名前を付けて (ファイル名) を保存"から保存し直せば良い。この時、"名前を付けてファイルを保存"ダイアログの"保存"ボタン右の下向き三角形をクリックし、"エンコード付きで保存"を使う必要が有る。

ただ単に警告が出るだけであれば、無視するなり、#pragma warning(disable: 4819)を指定するなりしても良いのだが、恐ろしい事に、他のエラーや警告を同時発生させる事がある。上に挙げたコードが正にその例となっており、文字コード誤判断の結果、error C2001とerror C2143が発生しているのが分かる。
warning C4819が発生している状態で、なおかつ原因の分からないコンパイルエラーが発生しているのであれば、コードの文字コードに注意を払う必要が有るだろう。

謝辞

THX @cpp_akira!!

何らかの理由により
コーディングにはVim使いたいとか。
VC++でコンパイル
VC++付属のclコマンドも含む。
BOM
UTF-8でのそれは、正確には"Byte Order Mark"という訳ではないが。
posted by 天井冴太 at 20:37| Comment(0) | TrackBack(0) | Tool | 更新情報をチェックする

2011年04月07日

Google Chromeでは、ローカル環境(fileスキーマ)下だと、object要素で読まれたHTMLから親のHTMLを読む事が出来ない

前回、object要素で読み込んだ(X)HTMLから、読み込み元のparam要素の内容を取得する方法の続き。

上記記事にて、

Chrome?さぁ、動くんじゃね?(投げやり)

……と、全くやる気がなかった件について。

先ずは前回のコードをローカル環境下のファイルに保存して、Chromeで開いてみてくれ。こいつをどう思う?
[動作せず]
すごく……動作してません……

そう、動作しない。HTTPでアクセスした場合は問題なく動作するのに、である。

Chromeのデベロッパーツールで確認してみると、in.htmlの16行目にてエラーが発生しているのが分かる。

in.html:16 Uncaught TypeError: Cannot call method 'getElementById' of undefined

……そんな馬鹿な!?

[window.parent.documentがundefined] 更に調べてみると、14行、window.parent.documentundefinedになっている事が分かる
[window.parentはDOMWindow型] window.parentは間違いなくDOMWindow型なのに、である。
undefinedな値にgetElementByIdメソッドが在る訳が無く、その結果、16行にてエラーが発生しているのだ。

これはバグ?それとも仕様?
仕様だとしたら一体どういう意図が……
HTTPサーバ立てて、そこで開発すれば問題は発生しないのだが、態々その為だけにサーバ導入するのも面倒だ……

posted by 天井冴太 at 04:40| Comment(0) | TrackBack(0) | Study | 更新情報をチェックする

2011年03月31日

object要素で読み込んだ(X)HTMLから、読み込み元のparam要素の内容を取得する方法

XHTMLHTML(以下単にHTMLと表記)のobject要素は、例えばFlashや各種動画ファイル等を読み込む為に使われるが、HTMLファイルを指定する事で、そのファイルをインラインフレーム表示出来る。

そして、object要素へ渡すパラメータ群は、子要素のparam要素で指定する事になっている。

……という事は、object要素で開いたHTMLからparam要素の内容を取得出来る筈だよね?という訳で調べてみた。

コード

結論としては以下の手法で。前者がobject要素を使う方(main.html)、後者がobject要素で読み込まれる方(in.html)。Firefox 4.0、Palemoon 3.6.15、Opera 11.0にて確認。

Chrome?さぁ、動くんじゃね?(投げやり)(別記事で言及する予定別記事にまとめた。Google Chromeでは、ローカル環境(fileスキーマ)下だと、object要素で読まれたHTMLから親のHTMLを読む事が出来ない)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>outer</title>
	<style type="text/css">/* <![CDATA[ */
		object { border: 1px dotted red; }
	/* ]]> */</style>
</head>

<body>
	<p>
		<object data="in.html" name="inner" id="inner">
			<param name="param1" value="value1" />
			<param name="param2" value="value2" />
		</object>
	</p>
</body>
</html>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>inner</title>
	<style type="text/css">/* <![CDATA[ */
		/* objectで現れる境界線を消す
		 * via: http://www.usamimi.info/~geko/arch_web/03_memo/001_object/index.html
		 */
		html, body { border-style: none; }
	/* ]]> */</style>
	<script type="application/javascript"> // <![CDATA[
		function hoge() {
			var outerDoc = window.parent.document;	// 外部のHTMLのdocumentオブジェクト
			var obj;
			obj = outerDoc.getElementById("inner");
			var params = obj.getElementsByTagName("param");	// param要素群

			// param要素群の名前と値をリストアップする
			var i;
			var table = document.createElement("table");
			for(i = 0; i < params.length; ++i) {
				var tr = document.createElement("tr");
				var th = document.createElement("th");
				var td = document.createElement("td");
				th.innerHTML = params.item(i).getAttribute("name");	// param要素のname属性
				td.innerHTML = params.item(i).getAttribute("value");	// param要素のvalue属性
				tr.appendChild(th);
				tr.appendChild(td);
				table.appendChild(tr);
			}
			document.getElementById("paramsC").appendChild(table);
		}

		window.addEventListener("load", hoge, false);
	// ]]></script>
</head>

<body>
	<div id="paramsC"></div>
</body>
</html>

実動サンプルはこちら

では解説

先ずはmain.htmlから。

<object data="in.html" name="inner" id="inner">
	<param name="param1" value="value1" />
	<param name="param2" value="value2" />
</object>

object要素のdata属性に、読み込むHTMLファイル(ここではin.html)を指定。また、id属性を設定している点に注意。このid属性を元に、in.html側からparam要素の読み取りを行う。

次にin.html

var outerDoc = window.parent.document;	// 外部のHTMLのdocumentオブジェクト
var obj;
obj = outerDoc.getElementById("inner");
var params = obj.getElementsByTagName("param");	// param要素群

window.parentが読み込み元のHTMLのWindowオブジェクトに相当する。そこからdocumentを取得すれば、読み込み元HTMLをDOMに従って読み出す事が出来る(ただし書き込みは出来ない)。

よって、window.parent.documentgetElementByIdメソッドで取得したいparam要素を持つobjectを取得し、更にそのオブジェクトのgetElementsByTagNameメソッドを呼び出す事でparam要素(群)を取得出来る。

th.innerHTML = params.item(i).getAttribute("name");
td.innerHTML = params.item(i).getAttribute("value");

後は普通に各param要素のDOMノードからgetAttributeメソッドでname属性、value属性を読み出す事が可能。

IEの話

[object要素で読み込んだHTMLからparam要素を参照するサンプルをIE8で表示させた画面]全く正常に動きません。
開発者ツールも何処が悪いか教えてくれないので、全く原因不明です。
さぁ皆様声を合わせて!

またIEか!!!!!

ラベル:HTML XHTML javascript
posted by 天井冴太 at 00:42| Comment(0) | TrackBack(1) | Study | 更新情報をチェックする

2011年02月17日

operator=()は継承されない

#include <iostream>
using namespace std;

class C {
public:
	C() : v(0) {}
	int operator=(const int &rhs) { return v = rhs; }
//	int operator+=(const int &rhs) { return v += rhs; }	←=以外は問題ない
	int v;
};

struct  D : public C {
};

int main()
{
	D d;
	cout << d.v << endl;
	d = 10;
	cout << d.v << endl;
}

これが通らない。例えばVC++2010だと、

test.cpp(19) : error C2679: 二項演算子 '=' : 型 'int' の右オペランドを扱う演算子が見つかりません (または変換できません)。
		test.cpp(13): 'D &D::operator =(const D &)' の可能性があります。
		引数リスト '(D, int)' を一致させようとしているとき

……という感じのコンパイルエラーが発生する。

Dクラスを以下のようにすれば問題ない。

struct  D : public C {
	using C::operator=;	// ←これが要る
//	int operator=(const int &rhs) { return C::operator=(rhs); }	// ←或いはこれ
};

コード全体(と、実行結果)はideone.comを。

OK、継承されないという事も回避策も分かった。だが何故継承されないという仕様になっているのだろう?

ラベル:C++
posted by 天井冴太 at 16:49| Comment(0) | TrackBack(0) | Study | 更新情報をチェックする

2010年12月09日

BOOST_PP_SEQ_FOR_EACHは、第1引数に指定したマクロの中でBOOST_PP_SEQ_FOR_EACHが使えない?

#include <iostream>
using namespace std;
 
#include <boost/preprocessor.hpp>
 
#define M2(r, data, elem) elem
#define M1(r, data, elem) BOOST_PP_SEQ_FOR_EACH(M2, data, elem)
 
int main()
{
        // M1のBOOST_PP_SEQ_FOR_EACHが解釈されない
        cout << BOOST_PP_STRINGIZE(BOOST_PP_SEQ_FOR_EACH(M1, data, ((1)(2)(3))((4)(5)(6)))) << endl;
 
        // M1を直接呼ぶと、~SEQ_FOR_EACHは解釈されている
        cout << BOOST_PP_STRINGIZE(M1(_, data, (10)(11)(12))) << endl;
        
        // BOOST_PP_SEQ_FOR_EACHで呼び出したマクロ中で、BOOST_PP_SEQ_FOR_EACHは使えないのか?
}

とすると、

BOOST_PP_SEQ_FOR_EACH(M2, data, (1)(2)(3)) BOOST_PP_SEQ_FOR_EACH(M2, data, (4)(5)(6))
10 11 12

これこの通り

上のコードはテストの為に単純化してて、これくらいならBOOST_PP_SEQ_FOR_EACH_PRODUCT使えばいけるんじゃないかなぁと思うけど、
内側のsequencesの特定の要素だけ別の処理を行いたい、といった場合は駄目だろうし。

うーん…………何でだろう?

posted by 天井冴太 at 19:00| Comment(0) | TrackBack(0) | Question | 更新情報をチェックする

2010年11月28日

Boost.PreprocessorのData Typesについて簡単にまとめてみる

どうにも同じようなC++コードを延々書かなければいけない→プリプロセサが在るじゃない!
という事で、C/C++でメタプログラミングをこなす為のライブラリであるBoost.Preprocessorに手を出した。

リファレンスはググったら簡単に見つかった

4つの型

さて、Boost.Preprocessorには4つの型が存在するようだ。全てマクロアーギュメントを複数格納するコンテナらしい。

オンラインリファレンスと、偶然図書館から借りていたC++テンプレートメタプログラミング(以下、単に『書籍』と表記)の付録Aを元にまとめてみる。同書籍に記述されている型名も括弧で囲って併記している。

sequences (列)

(a)(b)(c)のような、()で囲ったマクロアーギュメントの連続。

書籍によると、このライブラリのデータ構造の中で最も効率的で、最も柔軟性に富み、かつ最も使いやすいものであるとある。

要素数に制限無し。ただし、引数に数値を取るマクロでは256以下の値しか機能しない。尤も、BOOST_PP_SEQ_SUBSEQがあるし、それほど問題にはならないんじゃないだろうか?

tuples (タプル)

(a,b,c)のような、()の中でマクロアーギュメントを,で区切って記述したもの。

ランダムアクセスなど、いくつかの基本的な操作が用意されているらしいが、マクロの数も少なく(後述)、それ程実用的とは思えない……

関数やマクロの引数記述部分と同じ書き方というのが利点だろうか?

また、このデータ構造を操作する全てのマクロには、必ずtupleの要素数を指定しなければならない。つまりそれは、tupleの要素数を計算する方法がない、という事だろう。
arrays (配列)

(3, (a, b, c))のような、要素数と要素のtupleで構成されたもの。tupleの亜種と言えそうだ。

tupleと異なり、データ構造中にサイズを持つ

lists (リスト)

(a, (b, (c, BOOST_PP_NIL)))のような、『先頭要素とそれ以降のlist』で構成されたtuple亜種。終端にはBOOST_PP_NILを用いる必要がある。

LispのS式のように()の嵐になりそう。

これも、長さの制限は存在しない。

書籍によると、他の構造に比べて操作が遅くなりがちで、読みにくくなりがちなので、普通、最後の拠り所としてしか使われないとある。が、実はこのデータ構造を操作するマクロが一番多い(後述)。

データ構造中、或いはそれを扱うマクロの引数として、そのサイズが必要となるのがtuplesとarrays。それはつまり、自作マクロの引数としての利用は現実的ではないということだろう。その逆がsequencesとlists。

tuplesが一番C/C++の記述に近い。エディタ上での自動インデントの誤動作も少なくすみそう。これで、サイズを求める事さえ出来れば最高なのだが……

各型で可能な処理

……うーん、やっぱりよく分からない。いや表記の違いはよく分かったが、それぞれどういう時に使うのかがハッキリしない。

例えば、STL連接コンテナのvectorlistは違いがハッキリ分かる。vectorは要素の参照が素早く行える、listは要素の追加削除が容易。

Boost.Preprocessorの4つの型も、それぞれ何らかの長所短所がある筈だ。そうでなければ1つの型で充分な筈だし。

そこら辺をハッキリさせる為に、各型の操作を行うマクロをまとめてみた。『特定の操作を行うマクロが多ければ、その型はそれが得意と言う事だろう』という理屈。一つ一つ確認する余裕はないので、同じ名前のマクロは別の型を対象としていても同じ操作を提供する物と仮定。

arrays lists sequences tuples
マクロ数 16 44 36 7
BOOST_PP_ ~
LIST_APPEND


LIST_APPEND_D


LIST_AT


LIST_AT_D


LIST_CAT SEQ_CAT

LIST_CAT_D



SEQ_CAT_S

LIST_CONS*

ARRAY_DATA





TUPLE_EAT
ARRAY_ELEM
SEQ_ELEM TUPLE_ELEM

LIST_ENUM SEQ_ENUM

LIST_ENUM_R


LIST_FILTER SEQ_FILTER

LIST_FILTER_D



SEQ_FILTER_S

LIST_FIRST


LIST_FIRST_N SEQ_FIRST_N

LIST_FIRST_N_D


LIST_FOLD_LEFT SEQ_FOLD_LEFT

LIST_FOLD_LEFT_2ND*


LIST_FOLD_LEFT_2ND_D*


LIST_FOLD_LEFT_d


LIST_FOLD_LEFT_D*



SEQ_FOLD_LEFT_s

LIST_FOLD_RIGHT SEQ_FOLD_RIGHT

LIST_FOLD_RIGHT_2ND*


LIST_FOLD_RIGHT_2ND_D*


LIST_FOLD_RIGHT_d


LIST_FOLD_RIGHT_D*



SEQ_FOLD_RIGHT_s

LIST_FOR_EACH SEQ_FOR_EACH

LIST_FOR_EACH_I SEQ_FOR_EACH_I

LIST_FOR_EACH_I_R SEQ_FOR_EACH_I_R

LIST_FOR_EACH_PRODUCT SEQ_FOR_EACH_PRODUCT

LIST_FOR_EACH_PRODUCT_R SEQ_FOR_EACH_PRODUCT_R

LIST_FOR_EACH_R SEQ_FOR_EACH_R


SEQ_HEAD
ARRAY_INSERT
SEQ_INSERT
ARRAY_INSERT_D



LIST_IS_CONS SEQ_NIL

LIST_IS_NIL


LIST_NIL*

ARRAY_POP_BACK
SEQ_POP_BACK
ARRAY_POP_BACK_Z


ARRAY_POP_FRONT
SEQ_POP_FRONT
ARRAY_POP_FRONT_Z


ARRAY_PUSH_BACK
SEQ_PUSH_BACK
ARRAY_PUSH_FRONT
SEQ_PUSH_FRONT



TUPLE_REM



TUPLE_REM_CTOR
ARRAY_REMOVE
SEQ_REMOVE
ARRAY_REMOVE_D


ARRAY_REPLACE
SEQ_REPLACE
ARRAY_REPLACE_D



LIST_REST


LIST_REST_N SEQ_REST_N

LIST_REST_N_D

ARRAY_REVERSE LIST_REVERSE SEQ_REVERSE TUPLE_REVERSE

LIST_REVERSE_D



SEQ_REVERSE_S
ARRAY_SIZE LIST_SIZE SEQ_SIZE

LIST_SIZE_D



SEQ_SUBSEQ


SEQ_TAIL


SEQ_TO_ARRAY



TUPLE_TO_LIST



TUPLE_TO_SEQ

LIST_TO_TUPLE SEQ_TO_TUPLE

LIST_TO_TUPLE_R


LIST_TRANSFORM SEQ_TRANSFORM

LIST_TRANSFORM_D



SEQ_TRANSFORM_S

おい用意されているマクロ数に差が在りすぎるぞ。一番マクロが多いのがlists、一番少ないのがtuples。その差6倍。

さて、表にまとめてざっと眺めてみるに、次のような特徴が在りそうだ。

arrays
要素の追加削除に強い?
lists
その名の通り、順次処理に強いのだろうか。fold、for each、或いはreverseといった物が目立つ。
sequences
arraysとlistsの両方の特徴を併せ持っているように見える。ただし、それぞれの型で行える処理全てが可能という訳ではなさそうだ。
tuples
なにこれ。

tuplesの存在価値が謎。というかtuplesを操作するマクロの数が少な過ぎて判断が付かない。

各型の変換

表をまとめていて気づいたが、どうも、それぞれの型は相互変換可能という訳ではなさそうだ。図にまとめてみた。

[Boost.Preprocessor各型の変換マクロ一覧]listsとtuples、tuplesとsequencesは相互変換可能。sequencesからarrays、arraysからtuplesの変換は可能だが、その逆は用意されていない。 tuplesとlists、tuplesとsequencesは相互変換が可能。しかし、それ以外の変換は片方向のみ、或いは全く用意されていない。また、arraysに関してはtuplesへの変換しか用意されておらず、名称も他のものとは異なる。

マクロアーギュメント

書籍C++テンプレートメタプログラミングから用語を拝借。

マクロアーギュメントとは、次のものの空でない列である。

  • コンマでも括弧でもない、1つ以上のプリプロセッサトークン、および(または)
  • 左右の括弧に囲まれた、1つ以上のプリプロセッサトークン。
それ以外の変換は片方向のみ、或いは全く用意されていない
例えばlistsとsequencesの変換であれば、tuplesへの変換を経由すれば可能ではある。
ラベル:C++ boost
posted by 天井冴太 at 04:33| Comment(0) | TrackBack(0) | Study | 更新情報をチェックする

2010年10月07日

Rubyではメソッドは呼び出す前に定義してしまわなければならない

らしい。

以下のコードはダメ。

f

def f
	puts "call f"
end
/cygdrive/d/Documents and Settings/amaisaeta/test.rb:1: undefined local variable
or method `f' for main:Object (NameError)

なので、定義を先に書かなければならない。

def f
	puts "call f"
end

f
call f

最初、メソッドの定義を後回しにしてたらエラーになって驚いた。

えー、これダメなのか。メソッドの定義を後回しに出来る言語なんて沢山あるぞ。なんでダメなんだろう。どう考えても、後に書けた方が可読性高くなりそうなのに。

ラベル:ruby
posted by 天井冴太 at 03:21| Comment(0) | TrackBack(0) | Study | 更新情報をチェックする

2010年10月01日

例外のcatch時に変換関数は適用されない

いやようするに、

#include <iostream>
#include <stdexcept>
using namespace std;

struct C {
	operator runtime_error() {
		return runtime_error("original description");
	}
};

int main()
{
	try {
		throw C();
	} catch(runtime_error &) { // (1)ここには来ないで……
		cout << "catch std::runtime_error!" << endl;
	} catch(...) { // (2)ここに来る
		cout << "catch some type..." << endl;
	}
}

てな感じで、変換関数が定義されたクラスをthrowしても、catchする時にはそれは適用されない。らしい。驚いた。

なんかあんまり直感的でないなー。なんでこうなっているんだろう。

ラベル:C++
posted by 天井冴太 at 03:13| Comment(0) | TrackBack(0) | Study | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は90日以上新しい記事の投稿がないブログに表示されております。