クラスにある種の「型」パラメータを提供するライブラリを作成しているとします。これには、列挙型を使用できます。
namespace MyLib {
class Event {
public:
enum EventType { TYPE1, TYPE2, ... };
Event(EventType _type) : type(_type) { }
private:
EventType type;
}
}
次にインスタンス化します。
new MyLib::Event(Event::TYPE1);
ここまでは順調です。しかし、ユーザーがイベント タイプのリストを拡張できるようにしたい場合はどうでしょうか。type プロパティが列挙型の場合、これは不可能です。
低品質の可能性には、#define
カスタムイベント名を要求するか、単に文字列を使用することが含まれますが、どちらも最適ではないようです.
これに対する一般的な解決策はありますか?
1 つの提案はstruct EventType
、列挙型で指定された範囲内の値を返すために a を使用することです。ただし、これによりコンパイラの安全性の問題は解決されますが、名前付きの型を追加する問題は解決されません。ユーザーはこれらをグローバル スコープに追加する必要があります。
前者の問題ではなく後者に対処する 1 つの可能性は、EventType を整数型に typedef し、カスタム型をライブラリの名前空間または独自の名前空間に追加することをユーザーに任せることです。一意の値を提供するファクトリ メソッドは、Event の一部として提供できます。
#include <iostream>
#include <vector>
namespace MyLib {
namespace EventType {
typedef int T;
enum { TYPE1, TYPE2, Count};
}
class Event {
public:
Event(EventType::T _type) : type(_type) { }
EventType::T type;
static EventType::T registerType() { return _typeid++; }
private:
static int _typeid;
};
}
MyLib::EventType::T MyLib::Event::_typeid = EventType::Count;
// The user can then add types, including to the library's namespace
// (which may or may not be a good idea)
namespace MyLib { namespace EventType {
MyLib::EventType::T MYTYPE = MyLib::Event::registerType();
} }
int main() {
MyLib::Event ev1(MyLib::EventType::TYPE2);
MyLib::Event ev2(MyLib::EventType::MYTYPE);
std::cout << ev1.type << std::endl;
std::cout << ev2.type << std::endl;
return 0;
}
出力:
1
2
これはパラメーターを登録された型のセットに技術的に制限するものではありませんが、typedef と名前空間は、コンストラクター定義と IDE の自動提案で役立つ構文上の手がかりを提供し、ユーザー型がグローバル スコープを汚染するのを防ぎます。おそらくより大きな懸念事項です。
クラス、または一般的に関数/メソッドへの型パラメーターとして、有限でコンパイラーチェックされているがユーザーが拡張可能な値のセットを指定するより良い方法はありますか?