接受 std::vector<T> 或 std::array <T>的模板类



我正在尝试编写一个模板化的 getter 函数,该函数除外std::array<T>,并且还std::vector<T>具有T类型的任意内容并返回它的一个值

地图2d.h

#include <vector>
#include <array>
class Map2d {
private:
unsigned int m_width;
unsigned int m_height;
unsigned int m_size;
public:
Map2d(unsigned int width, unsigned int height)
: m_width(width), m_height(height) {
m_size = m_width * m_height;
}
template <typename T>
struct is_array_or_vector {
enum { value = false };
};
template <typename T, typename A>
struct is_array_or_vector<std::vector<T, A>> {
enum { value = true };
};
template <typename T, std::size_t N>
struct is_array_or_vector<std::array<T, N>> {
enum { value = true };
};
template <typename V, template <typename, typename...> class T, typename... Args>
typename std::enable_if<is_array_or_vector<T<V, Args...>>::value, V>::type
get(const T<V, Args...>& con, const unsigned int x, const unsigned int y) {
assert(con.size() <= m_size);
return con[m_width * y + x];
}
};

主.cpp

#include "Map2d.h"
int main() {
Map2d map(10, 10);
std::vector<int> v(100);
std::cout << map.get(v, 5, 5) << std::endl; // works
std::array<int, 100> a;
std::cout << map.get(a, 5, 5) << std::endl; // not working
std::list<int> l(100);
std::cout << map.get(l, 5, 5) << std::endl; // should not work
return 1;
}

我需要更改什么才能使其正常工作?我的版本可以与这个答案进行比较,不同之处在于返回值无效且不灵活。

我很感谢每一个提示! :)

template <typename T>
typename std::enable_if<is_array_or_vector<T>::value, typename T::value_type>::type
get(const T& con, const unsigned int x, const unsigned int y) {
assert(con.size() <= m_size);
return con[m_width * y + x];
}

如果不是 ,而是is_array_of_vector,则开发定义(或不定义)所包含类型的自定义类型特征,如下所示

template <typename>
struct enableAV
{ };
template <typename T, typename ... Ts>
struct enableAV<std::vector<T, Ts...>>
{ using type = T; };
template <typename T, std::size_t N>
struct enableAV<std::array<T, N>>
{ using type = T; };

您可以避免std::enable_if并简单地编写get()

如下所示
template <typename C>
typename enableAV<C>::type
get(C const & con, const unsigned int x, const unsigned int y)
{
assert(con.size() <= m_size);
return con[m_width * y + x];
}
namespace notstd {
namespace details {
template<template<class...>class, class, class...>
struct can_apply:std::false_type{};
template<class...>struct voider{using type=void;};
template<class...Ts>using void_t=typename voider<Ts...>::type;
template<template<class...>class Z, class...Ts>
struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply = details::can_apply<Z,void,Ts...>;
}
template<class T>
using dot_size_r = decltype( std::declval<T>().size() );
template<class T, class I=std::size_t>
using index_r = decltype( std::declval<T>()[ std::declval<I>() ] );
template<class T>
using can_dot_size = notstd::can_apply< dot_size_r, T >;
template<class T, class I=std::size_t>
using can_index = notstd::can_apply< index_r, T, I >;

can_dot_sizecan_index告诉您是否可以将类型T.size()d 并[]索引到其中。

template <typename C>
typename std::enable_if<
can_dot_size<C const&>{} && can_index<C const&, unsigned int>{},
typename std::decay<index_r<C const&, unsigned int>>::type
>::type
get(C const & con, const unsigned int x, const unsigned int y)
{
assert(con.size() <= m_size);
return con[m_width * y + x];
}

get适用于具有.size()方法和接受无符号 int 的[]索引的任何内容。

这包括std::arraystd::vectorstd::dequestd::string或其他一些假装类似数组的类型。

如果我们想限制为连续的容器,我们可能会要求.data()[],这可能是您的意图,而不是原始[]

相关内容

  • 没有找到相关文章

最新更新