[英]Use the value of strongly typed enum as index in boost::mpl::map
我正在使用定義類似於std::map<Foo, std::any>
的 C++ map 結構來存儲編譯器符號表的屬性。 Foo
是強類型枚舉,例如enum class Foo {ENUM}
。 在將一些其他類型轉換為std::any
之后,如果我通過Foo::ENUM
鍵訪問條目,我需要std::any_cast
將其轉換回來。 std::any_cast
的類型參數與Foo::ENUM
相關聯。
話雖這么說,我想要一些東西來自動確定基於Foo::ENUM
的std::any_cast
的類型參數,如下所示:
std::map<Foo, std::any> m;
const auto x = std::any_cast<some_magic(Foo::ENUM)::type>(m[Foo::ENUM]);
這是我當前的實現:
#include <iostream>
#include <string>
#include <vector>
#include <type_traits>
#include <any>
#include <map>
#define CAT(x, y) CAT_(x, y)
#define CAT_(x, y) x ## y
#define ENABLE_ENUM_TO_TYPE(enum_class_name) \
template <enum_class_name> struct CAT(enum_class_name, _enum_to_type);
#define ENUM_TYPE_PAIR(enum_class_name, enum_key, type_) \
template <> struct CAT(enum_class_name, _enum_to_type)<enum_class_name::enum_key> {using type = type_;};
enum class Foo {
A1, A2
};
enum class Bar {
B1, B2, B3
};
ENABLE_ENUM_TO_TYPE(Foo);
ENABLE_ENUM_TO_TYPE(Bar);
ENUM_TYPE_PAIR(Foo, A1, int);
ENUM_TYPE_PAIR(Foo, A2, double);
ENUM_TYPE_PAIR(Bar, B1, std::string);
ENUM_TYPE_PAIR(Bar, B2, std::vector<int>);
template <auto T1>
constexpr auto enum_to_type_impl() {
#define COMPARE_ENUM_CLASS(enum_class_name) \
if constexpr (std::is_same_v<decltype(T1), enum_class_name>) { return CAT(enum_class_name, _enum_to_type)<T1>{};} else
COMPARE_ENUM_CLASS(Foo)
COMPARE_ENUM_CLASS(Bar)
#undef COMPARE_ENUM_CLASS
{}
}
template <auto EnumVal>
struct enum_to_type {
using type = typename decltype(enum_to_type_impl<EnumVal>())::type;
};
int main() {
std::map<Bar, std::any> m;
m[Bar::B1] = std::string{"Hello"};
std::cout << std::any_cast<enum_to_type<Bar::B1>::type>(m[Bar::B1]) << std::endl;
return 0;
}
但是,我上面的代碼仍然很麻煩。 我查看了 boost mpl 庫,但顯然它不提供類似mpl::enum_
的東西,我嘗試了以下代碼,但它不起作用:
#include <boost/mpl/map.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/at.hpp>
#include <string>
#include <iostream>
enum class Bar {
C1, C2
};
template <auto EnumVal> struct enum_
{
using type = enum_;
using value_type = decltype(EnumVal);
typedef mpl_::integral_c_tag tag;
};
typedef boost::mpl::map<
boost::mpl::pair<enum_<Bar::C1>, std::string>,
boost::mpl::pair<enum_<Bar::C2>, int>
> m;
int main() {
boost::mpl::at<m, enum_<Bar::C1>>::type x;
return 0;
}
編譯上面的代碼時,出現以下錯誤消息:
main.cpp: In function ‘int main()’:
main.cpp:24:38: error: incomplete type ‘boost::mpl::at<boost::mpl::map<boost::mpl::pair<enum_<Bar::C1>, std::__cxx11::basic_string<char> >, boost::mpl::pair<enum_<Bar::C2>, int> >, enum_<Bar::C1> >’ used in nested name specifier
24 | boost::mpl::at<m, enum_<Bar::C1>>::type x;
有任何想法嗎? boost::mpl::map
的數據類型是否可擴展?
編輯:我在上面的代碼片段中添加了#include <boost/mpl/at.hpp>
接受的答案之后,它工作正常。 至於boost::mp11的解決方案,我的代碼在https://godbolt.org/z/KvjecnTe3 ,但是gcc編譯失敗,我在https上提交了issue://github.com/boostorg/mp11 /問題/72 。
您需要包含#include <boost/mpl/at.hpp>
。 另外,我不推薦使用 boost::mpl - 它編譯起來真的很慢。 您的“笨重”解決方案是最快的恕我直言,如果您不喜歡它,您可能希望看看 boost::mp11 或任何其他“更現代”的元編程庫。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.