区分具有类型特征的结构体
Distinguishing structs with type traits
是否有办法将具有std::vector<T>
的struct
与任何其他类型区分开来?
我有一些模板函数,如果T
是一个包含std::vector<T>
的结构体,那么我要找的是:
template<typename T> method(const T& object)
{
static_assert(!contains_vector<T>::value, "This method must be specialized");
// implementation
}
,
struct Foo {
uint32_t foo;
float bar;
};
struct Bar {
uint16_t foo;
vector<float> bar;
}
contains_vector<float>::value == false;
contains_vector<Foo>::value == false;
contains_vector<Bar>::value == true;
我试图弄清楚如何通过<type_traits>
来区分这种差异。
一般情况下,没有。c++没有反射。所以,如果你想写一个类型trait"这个任意的泛型结构是否包含一个vector
成员?",这是不可能的。
然而,如果你控制了所有你想测试的类型,你可以用BOOST_FUSION_ADAPT_STRUCT
来检测它们,这就增加了反射:
BOOST_FUSION_ADAPT_STRUCT(
Foo,
(uint32_t, foo)
(float, bar)
)
BOOST_FUSION_ADAPT_STRUCT(
Bar,
(uint16_t, foo)
(std::vector<float>, bar)
)
这使得结构体Foo
和Bar
从一开始就像boost::fusion
序列一样起作用。之后,编写类型trait只涉及所有常见的Boost Fusion元编程技巧:
template <typename Seq>
struct contains_vector {
// metafunction class for checking if a type is a std::vector<T,A>
struct is_vector {
template <typename T>
struct apply : std::false_type { };
template <typename T, typename A>
struct apply<std::vector<T,A>> : std::true_type { };
};
// think std::find_if()
using iter = typename boost::fusion::result_of::find_if<Seq, is_vector>::type;
// think .end()
using end = typename boost::fusion::result_of::end<Seq>::type;
// if iter == end, it's not found, so have to flip the sign
using type = std::integral_constant<bool, !std::is_same<iter, end>::value>;
};
与:static_assert(contains_vector<Bar>::type::value, ""); // OK
static_assert(!contains_vector<Foo>::type::value, ""); // OK
请注意,我使用find_if
和end
而不是使用any
,因为那一个作为元函数总是返回bool
。
您应该考虑使用SFINAE(替换失败不是错误)
struct Foo {
uint32_t foo;
float bar;
};
struct Bar {
typedef vector<float> bar_vector;
uint16_t foo;
bar_vector bar;
};
注意在struct Bar中增加了typepedef。
template <typename T>
struct contains_vector {
// Types "yes" and "no" are guaranteed to have different sizes,
// specifically sizeof(yes) == 1 and sizeof(no) == 2.
typedef char yes[1];
typedef char no[2];
template <typename C>
static yes& test(typename C::bar_vector*);
template <typename>
static no& test(...);
// If the "sizeof" of the result of calling test<T>(nullptr) is equal to sizeof(yes),
// the first overload worked and T has a nested type named foobar.
static const bool value = sizeof(test<T>(nullptr)) == sizeof(yes);
};
然后可以确定该结构体是否包含指示存在vector的类型定义:
std::cout << contains_vector<int>::value << std::endl;
std::cout << contains_vector<Bar>::value << std::endl;
std::cout << contains_vector<Foo>::value << std::endl;
可以在c++ 11中简化
相关文章:
- 根据用户回答声明"Players"。用户选择玩家数量。播放器是结构体
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 包含 std::list 的结构体的 C++ 初始化
- 结构体和类的不同大小(),彼此具有相同的字段类型
- 如何使用结构体的向量数组?
- 如何使用结构体在C++中更改这些代码?
- 无法在 Mosquitto MQTT Broker 插件上访问结构体 mosquitto 的元素
- 我应该如何在C++中使用结构体解决输入失败的问题?
- Qsort() 比较结构体整数的总和
- 如何使用迭代器指向结构体c++的向量
- 在C++中使用链表的堆栈实现中,访问结构体headNode成员count和top会导致运行时错误
- 如何获取结构体成员的地址
- 创建结构体向量,表达式:向量下标超出范围
- boost::任何带有结构体和无符号整数
- 如何在构造函数中初始化结构体的动态数组?
- 只写结构体的某些字段
- C++ push_back() 一个结构体到一个向量中
- C++14 结构体上的统一初始化
- 区分具有类型特征的结构体