使用 boost::mpl 获取 boost::variant 的类型索引
Get boost::variant's type index with boost::mpl
boost::variant 有成员 types,这是某种 boost::mpl 结构。
有没有办法在编译时获取该结构中的类型索引,所以在运行时后期我可以做
if(myVariantInstance.which() == typeIndex)
{
/*...*/
}
而不是
if(myVariantInstance.type() == typeid(ConcreteType))
{
/*...*/
}
有点绕,可能还有更好的办法,不过你可以用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");
如果您有兴趣,我找到了在没有 boost::mpl 的情况下获取 boost::variant 类型索引的解决方案。
#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
#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::variant 有成员 types,这是某种 boost::mpl 结构。 有没有办法在编译时获取该结构中的类型索引,所以在运行时后期我可以做
if(myVariantInstance.which() == typeIndex)
{
/*...*/
}
而不是
if(myVariantInstance.type() == typeid(ConcreteType))
{
/*...*/
}
有点绕,可能还有更好的办法,不过你可以用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");
如果您有兴趣,我找到了在没有 boost::mpl 的情况下获取 boost::variant 类型索引的解决方案。
#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
#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 已经提供了一个——仅用于解释目的...