检查容器类型
Check for container type
如何检查容器类型? IE。
template <class Container1>
void func (Container1 &cont_1)
{
if (cont_1 is list container)
//do stuff
if (cont_1 is vector container)
//do other stuff
}
我仅有的两种可能性是列表和向量。请注意,我不知道 list
/vector
中的值类型,即 vector<char>
或 vector<int>
等是可能的,因此我只想获取信息获取向量或列表。
我遇到了 typeid
和 type info
,但没有真正完成它。
您可以使用函数重载来实现:
template<typename T>
void func(std::vector<T>& vec)
{
//Do something with vector
}
template<typename T>
void func(std::list<T>& list)
{
//Do something with list
}
或者使用 typeid
,这可能不太理想,因为任何一种情况下的代码都必须为 std::vector
和 std::list
编译,因为模板在编译时,即使分支可能不会在 std::list
上执行,编译器此时也不知道这一点,因此它将无法编译,试图在 std::vector
上应用操作std::list
.
template<template<typename, typename> class C, typename T, typename Alloc>
void func(C<T, Alloc>& container)
{
if (typeid(container).hash_code() == typeid(std::vector<T, Alloc>&).hash_code())
; //Do something with vector
else if (typeid(container).hash_code() == typeid(std::list<T, Alloc>&).hash_code())
; //Do something with list
}
您可以使用可变参数模板编写一些测试:
#include <vector>
// is_vector
// =========
namespace Detail {
template<typename T>
struct is_vector_type : std::false_type
{};
template<typename ... Types>
struct is_vector_type<std::vector<Types...>> : std::true_type
{};
}
template<typename T>
struct is_vector_type : Detail::is_vector_type<typename std::decay<T>::type>
{};
template<typename T>
constexpr bool is_vector(T&&) {
return is_vector_type<T>();
}
// Test
// ====
#include <iostream>
template <class Container>
void func (Container &container)
{
if (is_vector_type<Container>()) {
std::cout << "vector\n";
}
// or
if (is_vector(container)) {
std::cout << "vector\n";
}
// ...
}
int main() {
std::vector<int> v;
func(v);
static_assert(is_vector(v), "");
}
重载的方法当然更好,但为了完整起见,还有另一种使用 sfinae 机制的方法。在 c++11 之前,示例代码如下所示:
#include <iostream>
#include <vector>
#include <list>
template <bool V, class T = void>
struct enable_if { };
template <class T>
struct enable_if<true, T> {
typedef T type;
};
struct true_type {
static const bool value = true;
};
struct false_type {
static const bool value = false;
};
template <class T>
struct is_list: false_type {};
template <class T>
struct is_list<typename std::list<T> >: true_type { };
template <class T>
struct is_vector: false_type { };
template <class T>
struct is_vector<typename std::vector<T> >: true_type { };
template <class C>
typename enable_if<is_vector<C>::value>::type func(C &c) {
// c is a vector here
std::cout << "This is a vector" << std::endl;
}
template <class C>
typename enable_if<is_list<C>::value>::type func(C &c) {
// c is a list here
std::cout << "This is a list" << std::endl;
}
int main() {
std::vector<int> v;
func(v);
std::list<int> l;
func(l);
}
在 c++11 中它会变得更简单一些:
#include <iostream>
#include <vector>
#include <list>
#include <type_traits>
template <class T>
struct is_list: std::false_type {};
template <class T>
struct is_list<typename std::list<T>>: std::true_type { };
template <class T>
struct is_vector: std::false_type { };
template <class T>
struct is_vector<typename std::vector<T>>: std::true_type { };
template <class C>
typename std::enable_if<is_vector<C>::value>::type func(C &c) {
// c is a vector here
std::cout << "This is a vector" << std::endl;
}
template <class C>
typename std::enable_if<is_list<C>::value>::type func(C &c) {
// c is a list here
std::cout << "This is a list" << std::endl;
}
int main() {
std::vector<int> v;
func(v);
std::list<int> l;
func(l);
}
如何检查容器类型? IE。
template <class Container1>
void func (Container1 &cont_1)
{
if (cont_1 is list container)
//do stuff
if (cont_1 is vector container)
//do other stuff
}
我仅有的两种可能性是列表和向量。请注意,我不知道 list
/vector
中的值类型,即 vector<char>
或 vector<int>
等是可能的,因此我只想获取信息获取向量或列表。
我遇到了 typeid
和 type info
,但没有真正完成它。
您可以使用函数重载来实现:
template<typename T>
void func(std::vector<T>& vec)
{
//Do something with vector
}
template<typename T>
void func(std::list<T>& list)
{
//Do something with list
}
或者使用 typeid
,这可能不太理想,因为任何一种情况下的代码都必须为 std::vector
和 std::list
编译,因为模板在编译时,即使分支可能不会在 std::list
上执行,编译器此时也不知道这一点,因此它将无法编译,试图在 std::vector
上应用操作std::list
.
template<template<typename, typename> class C, typename T, typename Alloc>
void func(C<T, Alloc>& container)
{
if (typeid(container).hash_code() == typeid(std::vector<T, Alloc>&).hash_code())
; //Do something with vector
else if (typeid(container).hash_code() == typeid(std::list<T, Alloc>&).hash_code())
; //Do something with list
}
您可以使用可变参数模板编写一些测试:
#include <vector>
// is_vector
// =========
namespace Detail {
template<typename T>
struct is_vector_type : std::false_type
{};
template<typename ... Types>
struct is_vector_type<std::vector<Types...>> : std::true_type
{};
}
template<typename T>
struct is_vector_type : Detail::is_vector_type<typename std::decay<T>::type>
{};
template<typename T>
constexpr bool is_vector(T&&) {
return is_vector_type<T>();
}
// Test
// ====
#include <iostream>
template <class Container>
void func (Container &container)
{
if (is_vector_type<Container>()) {
std::cout << "vector\n";
}
// or
if (is_vector(container)) {
std::cout << "vector\n";
}
// ...
}
int main() {
std::vector<int> v;
func(v);
static_assert(is_vector(v), "");
}
重载的方法当然更好,但为了完整起见,还有另一种使用 sfinae 机制的方法。在 c++11 之前,示例代码如下所示:
#include <iostream>
#include <vector>
#include <list>
template <bool V, class T = void>
struct enable_if { };
template <class T>
struct enable_if<true, T> {
typedef T type;
};
struct true_type {
static const bool value = true;
};
struct false_type {
static const bool value = false;
};
template <class T>
struct is_list: false_type {};
template <class T>
struct is_list<typename std::list<T> >: true_type { };
template <class T>
struct is_vector: false_type { };
template <class T>
struct is_vector<typename std::vector<T> >: true_type { };
template <class C>
typename enable_if<is_vector<C>::value>::type func(C &c) {
// c is a vector here
std::cout << "This is a vector" << std::endl;
}
template <class C>
typename enable_if<is_list<C>::value>::type func(C &c) {
// c is a list here
std::cout << "This is a list" << std::endl;
}
int main() {
std::vector<int> v;
func(v);
std::list<int> l;
func(l);
}
在 c++11 中它会变得更简单一些:
#include <iostream>
#include <vector>
#include <list>
#include <type_traits>
template <class T>
struct is_list: std::false_type {};
template <class T>
struct is_list<typename std::list<T>>: std::true_type { };
template <class T>
struct is_vector: std::false_type { };
template <class T>
struct is_vector<typename std::vector<T>>: std::true_type { };
template <class C>
typename std::enable_if<is_vector<C>::value>::type func(C &c) {
// c is a vector here
std::cout << "This is a vector" << std::endl;
}
template <class C>
typename std::enable_if<is_list<C>::value>::type func(C &c) {
// c is a list here
std::cout << "This is a list" << std::endl;
}
int main() {
std::vector<int> v;
func(v);
std::list<int> l;
func(l);
}