Skip to content

Instantly share code, notes, and snippets.

@maraigue
Created December 12, 2011 20:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maraigue/1468990 to your computer and use it in GitHub Desktop.
Save maraigue/1468990 to your computer and use it in GitHub Desktop.
[C++] いくつかの特定の型のみを引数に取れる関数を定義する
#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