Created
December 12, 2011 20:40
-
-
Save maraigue/1468990 to your computer and use it in GitHub Desktop.
[C++] いくつかの特定の型のみを引数に取れる関数を定義する
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
// ------------------------------------------------------------ | |
// いくつかの特定の型のみを引数に取れる関数を定義する | |
// ------------------------------------------------------------ | |
// [動機] | |
// 「引数にはクラスAかクラスBのインスタンスのみ渡せる」ような | |
// 関数を定義するにあたって、 | |
// ●どちらのクラスのインスタンスが来ても処理はほぼ同じな上、 | |
// そんな関数が多数あるので、単純なオペレータオーバーロードには | |
// したくない(大量にオペレータオーバーロードの定義を書くことに | |
// なってしまうため)。 | |
// ●他のクラスのインスタンスが渡された場合は、確実にコンパイル | |
// エラーにしたい(よって、template <class TYPE> hoge(TYPE val); | |
// というだけの定義にはしたくない)。 | |
// ●こういうときはvirtualクラスを使って、AとBを一つのvirtual | |
// クラスから派生させれば一応解決はするのだが、メモリ量が | |
// シビアなので、virtualクラスも使いたくない。 | |
// それを無理やりテンプレートで解決したのがこのコードです。 | |
// ------------------------------------------------------------ | |
// ※「関数テンプレートにデフォルト引数を与える」ため | |
// C++11(C++0x)対応コンパイラでないとコンパイルできない | |
// 可能性が高いです。 | |
// (GCCの場合、GCC4.3以上で、かつコンパイル時に -std=c++0x | |
// オプションが必要。例: | |
// $ g++ -std=c++0x any_type_haveing.cpp) | |
// ------------------------------------------------------------ | |
// 何かBoostあたりにいい解決策がありそうな気がしなくもないので | |
// いい方法があったら教えて下さい m(_ _)m | |
// ------------------------------------------------------------ | |
// is_animalを持つ型TYPEについては template <class TYPE> として働き | |
// そうでない型についてはコンパイルエラーを出すようなマクロ | |
#define FOR_ANIMAL_TYPE(x) \ | |
template <class x, class DUMMY_ = typename x::is_animal> | |
// ここで、「中にis_animal型を持つ型」のみを引数に取れる関数を定義する | |
// 他の関数も、 | |
FOR_ANIMAL_TYPE(X) void show_age(const X & animal){ | |
std::cout << animal.age() << std::endl; | |
} | |
// 上記の関数にどちらを渡しても同様にふるまうようにしたい | |
// クラス2つを定義。「struct is_animal{};」を両方に定義したことで | |
// 実現している。 | |
class Tsuru{ | |
public: | |
struct is_animal{}; | |
int age() const { return 1000; } | |
}; | |
class Kame{ | |
public: | |
struct is_animal{}; | |
int age() const { return 10000; } | |
}; | |
int main(){ | |
Tsuru crane; | |
Kame tortoise; | |
show_age(crane); | |
show_age(tortoise); | |
//show_age(20); // コンパイルエラー。int::is_animalは存在しない | |
//show_age(std::cout); // コンパイルエラー。同様 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment