有没有办法区分struct
哪个std::vector<T>
与其他任何类型?
我有一些模板函数,如果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>
这种差异。
答案 0 :(得分:2)
在一般情况下,没有。 C ++没有反射。因此,如果你想写一个类型特征“这个任意泛型结构包含一个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
个序列一样。在那之后,写一个类型特征只涉及所有常见的Boost Fusion元编程hackery:
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
答案 1 :(得分:0)
您应该考虑使用SFINAE(替换失败不是错误)
struct Foo {
uint32_t foo;
float bar;
};
struct Bar {
typedef vector<float> bar_vector;
uint16_t foo;
bar_vector bar;
};
注意在struct Bar中添加了typedef。
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);
};
然后,您可以确定结构是否包含指示存在向量的typedef:
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中进行简化。