获取 boost::variant 的类型索引与 boost::mpl
Get boost::variant's type index with boost::mpl
boost::variant具有成员类型,这是某种boost::mpl结构。有没有一种方法可以在编译时在该结构中获得类型的索引,以便在运行时后期进行
if(myVariantInstance.which() == typeIndex)
{
/*...*/
}
代替
if(myVariantInstance.type() == typeid(ConcreteType))
{
/*...*/
}
如果您感兴趣,我找到了在没有boost::mpl的情况下在boost:中获取类型索引的解决方案。
#include <iostream>
#include <type_traits>
#include <boost/variant/variant.hpp>
using myvariant = boost::variant<int, bool, double, int>;
template <typename T, typename ... Ts>
struct type_index;
template <typename T, typename ... Ts>
struct type_index<T, T, Ts ...>
: std::integral_constant<std::size_t, 0>
{};
template <typename T, typename U, typename ... Ts>
struct type_index<T, U, Ts ...>
: std::integral_constant<std::size_t, 1 + type_index<T, Ts...>::value>
{};
template <typename T, typename ... Ts>
struct variant_first_same_type_idx;
template <typename T, typename Head, typename ... Tail>
struct variant_first_same_type_idx<T, boost::variant<Head, Tail ... >>
: type_index<T, Head, Tail ...>
{};
int main()
{
std::cout << variant_first_same_type_idx<int, myvariant>::value << std::endl;
std::cout << variant_first_same_type_idx<bool, myvariant>::value << std::endl;
std::cout << variant_first_same_type_idx<double, myvariant>::value << std::endl;
}
该程序的输出为:
0
1
2
C++17的更新:
#include <iostream>
#include <stdexcept>
#include <type_traits>
#include <boost/variant/variant.hpp>
using myvariant = boost::variant<int, bool, double, int>;
// std::type_identity in C++20
template <typename T>
struct type_identity
{
using type = T;
};
template <typename T, typename... Ts>
constexpr std::size_t get_same_type_idx(type_identity<boost::variant<Ts...>>)
{
const bool is_same[]{std::is_same_v<Ts, T>...};
// std::find in C++20
for (std::size_t i = 0; i < sizeof...(Ts); ++i)
{
if (is_same[i])
{
return i;
}
}
throw std::out_of_range("Type not found");
}
template <typename T, typename V>
constexpr std::size_t variant_first_same_type_idx = get_same_type_idx<T>(type_identity<V>{});
int main()
{
std::cout << variant_first_same_type_idx<int, myvariant> << std::endl;
std::cout << variant_first_same_type_idx<bool, myvariant> << std::endl;
std::cout << variant_first_same_type_idx<double, myvariant> << std::endl;
}
这有点复杂,可能有更好的方法,但您可以使用boost::mpl::copy。根据您评论中的示例,以下内容应该有效:
#include <boost/variant.hpp>
#include <boost/mpl/copy.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/vector.hpp>
typedef boost::mpl::vector<int, long, char> MyMplVector;
typedef boost::mpl::find<MyMplVector, long>::type MyMplVectorIter;
static_assert(MyMplVectorIter::pos::value == 1, "Error");
typedef boost::variant<int, long, char> MyVariant;
typedef boost::mpl::vector<> EmptyVector;
typedef boost::mpl::copy<
MyVariant::types,
boost::mpl::back_inserter<EmptyVector>>::type ConcatType;
typedef boost::mpl::find<ConcatType, long>::type MyVariantTypesIter;
static_assert(MyVariantTypesIter::pos::value == 1, "Error");
#include <boost/mpl/index_of.hpp>
#include <iostream>
typedef boost::variant<int, std::string> VARIANT;
std::ostream &operator<<(std::ostream &_rS, const VARIANT&_r)
{ switch (_r.which())
{ default:
return _rS << "what the *";
case boost::mpl::index_of<VARIANT::types, int>::type::value:
return _rS << boost::get<int>(_r);
case boost::mpl::index_of<VARIANT::types, std::string>::type::value:
return _rS << boost::get<std::string>(_r);
}
}
PS。我一直对使用访问者访问模式的人感到好奇。。。
PPS。我知道不需要将输出操作符实现为boost::variant已经提供了一个——只是为了解释的目的。。。
相关文章:
- 为什么 Boost multi_index只修改第一个索引的键时对第二个索引进行比较?
- 在擦除或修改作为不同索引键的值时,boost::multi_index 迭代器是否无效?
- 如何从 boost::container::vector<std::string>::iterator 访问索引和对象?
- 从 boost::variant 中逐个索引获取项目,就像使用 std::variant 一样
- 如何使equal_range迭代器在 Boost 多索引中按不同的索引排序?
- C++ boost::multi_array索引太大
- 如何将值插入到 c++ boost::multiindex 集合的特定索引中,就像在 std::list 中一样
- 通过索引操作员插入boost :: program_options :: variables_map
- 如何使用 Boost V2 1.70 日志记录库在第一个索引(例如 logtrail01.txt)保留最新的日志文件名?
- 如何在不重新索引顶点的情况下调用"boost::remove_vertex"?
- 修改Boost多索引项的非索引字段的最佳方法:modify vs mutable
- 使用Boost.Preprocessor生成类模板的一组标记和索引的专门化
- 我是否需要通过锁来保护对 Boost MultiIndex 索引(索引本身)的访问?
- 存储Boost Multi_index索引迭代器
- 使用Boost Multi_multi索引
- 在Boost多索引容器中搜索位字段数据
- 获取 boost::variant 的类型索引与 boost::mpl
- boost ::几何查询返回索引
- 在Boost :: Dynamic_bitset中提取设置的位索引
- Boost::Spirit::QI解析器:已解析元素的索引