ページへ戻る
印刷
技術系備忘録/C++/小技/型で条件分岐
をテンプレートにして作成 ::
シンクリッジ
xpwiki
:技術系備忘録/C++/小技/型で条件分岐 をテンプレートにして作成
開始行:
変数の型によって処理を切り替えたいことが稀によくあるんじ...
C++ では RTTI なる情報で実行時に型を判断出来るので以下の...
#prettify{{
struct Animal {
virtual ~Animal() {} // ポリモーフィックにする
};
struct Dog : public Animal {};
struct Cat : public Animal {};
void func(Animal* p) {
if (typeid(*p) == typeid(Dog)) { // 型が Dog なら
// ・・・
} else if (typeid(*p) == typeid(Cat)) { // 型が Cat なら
// ・・・
}
}
}}
&font(70%){コンパイル時に型が判明する場合は if constexpr ...
これで十分事足りるのですが、もう少し粋に書きたい場合もあ...
if 文の羅列ではなく switch~case みたいな感じで。
がしかし switch~case で分岐できる式は整定数式のみです。
そこで、switch~case とまではいきませんがそれっぽい条件分...
&font(70%){std::type_index は C++11 から使えますが、以下...
#prettify{{
int main(void){
using namespace std;
// クラス定義
struct Car {
virtual ~Car() {}
};
struct Nissan : public Car {};
struct Silvia : public Nissan {};
struct Skyline : public Nissan {};
struct Toyota : public Car {};
struct Chaser : public Toyota {};
const std::vector<std::shared_ptr<Car>> v = { // サンプル
make_shared<Nissan>(),
make_shared<Silvia>(),
make_shared<Skyline>(),
make_shared<Toyota>(),
make_shared<Chaser>(),
make_shared<Car>(),
};
// それぞれの型に対応したコードを std::map で構築
// 注: static 変数であることが実行速度では有利です(この...
static const std::map<std::type_index, std::function<voi...
{typeid(Nissan), [] {
cout << "NISSAN" << endl;
}},
{typeid(Silvia), [] {
cout << "NISSAN SILVIA" << endl;
}},
{typeid(Skyline), [] {
cout << "NISSAN SKYLINE" << endl;
}},
{typeid(Toyota), [] {
cout << "TOYOTA" << endl;
}},
{typeid(Chaser), [] {
cout << "TOYOTA CHASER" << endl;
}},
};
for (const auto i : v) {
if (auto j = map.find(typeid(*i)); j != map.end()) { //...
j->second(); // 実行
} else {
cout << "unknown" << endl; // 定義ナシ
}
}
}
}}
実行結果
NISSAN
NISSAN SILVIA
NISSAN SKYLINE
TOYOTA
TOYOTA CHASER
unknown
この程度のボリュームの例でも、if 文の羅列よりは見通しもよ...
ちなみに C++03 くらいのコンパイラでも RTTI がサポートされ...
C++は難しげな機能も沢山追加されていますが地味な改修もとて...
C++関係者の皆様には感謝です。
終了行:
変数の型によって処理を切り替えたいことが稀によくあるんじ...
C++ では RTTI なる情報で実行時に型を判断出来るので以下の...
#prettify{{
struct Animal {
virtual ~Animal() {} // ポリモーフィックにする
};
struct Dog : public Animal {};
struct Cat : public Animal {};
void func(Animal* p) {
if (typeid(*p) == typeid(Dog)) { // 型が Dog なら
// ・・・
} else if (typeid(*p) == typeid(Cat)) { // 型が Cat なら
// ・・・
}
}
}}
&font(70%){コンパイル時に型が判明する場合は if constexpr ...
これで十分事足りるのですが、もう少し粋に書きたい場合もあ...
if 文の羅列ではなく switch~case みたいな感じで。
がしかし switch~case で分岐できる式は整定数式のみです。
そこで、switch~case とまではいきませんがそれっぽい条件分...
&font(70%){std::type_index は C++11 から使えますが、以下...
#prettify{{
int main(void){
using namespace std;
// クラス定義
struct Car {
virtual ~Car() {}
};
struct Nissan : public Car {};
struct Silvia : public Nissan {};
struct Skyline : public Nissan {};
struct Toyota : public Car {};
struct Chaser : public Toyota {};
const std::vector<std::shared_ptr<Car>> v = { // サンプル
make_shared<Nissan>(),
make_shared<Silvia>(),
make_shared<Skyline>(),
make_shared<Toyota>(),
make_shared<Chaser>(),
make_shared<Car>(),
};
// それぞれの型に対応したコードを std::map で構築
// 注: static 変数であることが実行速度では有利です(この...
static const std::map<std::type_index, std::function<voi...
{typeid(Nissan), [] {
cout << "NISSAN" << endl;
}},
{typeid(Silvia), [] {
cout << "NISSAN SILVIA" << endl;
}},
{typeid(Skyline), [] {
cout << "NISSAN SKYLINE" << endl;
}},
{typeid(Toyota), [] {
cout << "TOYOTA" << endl;
}},
{typeid(Chaser), [] {
cout << "TOYOTA CHASER" << endl;
}},
};
for (const auto i : v) {
if (auto j = map.find(typeid(*i)); j != map.end()) { //...
j->second(); // 実行
} else {
cout << "unknown" << endl; // 定義ナシ
}
}
}
}}
実行結果
NISSAN
NISSAN SILVIA
NISSAN SKYLINE
TOYOTA
TOYOTA CHASER
unknown
この程度のボリュームの例でも、if 文の羅列よりは見通しもよ...
ちなみに C++03 くらいのコンパイラでも RTTI がサポートされ...
C++は難しげな機能も沢山追加されていますが地味な改修もとて...
C++関係者の皆様には感謝です。
ページ名: