主にテンプレートに基づく可能な解決策を次に示します。
#include<cstddef>
#include<functional>
#include<iostream>
template<typename T>
struct wrapper {
using type = T;
constexpr wrapper(std::size_t N): N{N} {}
const std::size_t N;
};
template<typename... T>
struct identifier: wrapper<T>... {
template<std::size_t... I>
constexpr identifier(std::index_sequence<I...>): wrapper<T>{I}... {}
template<typename U>
constexpr std::size_t get() const { return wrapper<U>::N; }
};
template<typename... T>
constexpr identifier<T...> ID = identifier<T...>{std::make_index_sequence<sizeof...(T)>{}};
// ---
struct A {};
struct B {};
constexpr auto id = ID<A, B>;
int main() {
switch(id.get<B>()) {
case id.get<A>():
std::cout << "A" << std::endl;
break;
case id.get<B>():
std::cout << "B" << std::endl;
break;
}
}
これには C++14 が必要であることに注意してください。
シーケンシャル ID をタイプのリストに関連付けるために必要なことは、上記の例のように、そのリストをテンプレート変数に提供することだけです。
constexpr auto id = ID<A, B>;
get
その時点から、メソッドを使用して、指定されたタイプの指定された ID を取得できます。
id.get<A>()
それだけです。switch
要求に応じて、コード例に示されているように、ステートメントで使用できます。
数値 ID を関連付けるクラスのリストに型が追加されている限り、各コンパイル後および各実行中の識別子は同じであることに注意してください。
リストからタイプを削除したい場合でも、例として偽のタイプをプレースホルダーとして使用できます。
template<typename> struct noLonger { };
constexpr auto id = ID<noLonger<A>, B>;
これによりA
、 に関連付けられた ID がなくなり、 に指定された IDB
が変更されなくなります。
絶対に削除したくない場合はA
、次のようなものを使用できます。
constexpr auto id = ID<noLonger<void>, B>;
または何でも。