我需要创建一个可以保存相同类型但具有不同维度的boost :: multi_array的类
假设有一个或多个这样的Double
数组boost::multi_array<double, 2> array_2d; //2D array
boost::multi_array<double, 3> array_3d; //4D array
boost::multi_array<double, 4> array_4d; //5D array
etc...
我需要一个容器类,它可以容纳所有上述类型,以便在以后需要时使用正确的类型
类似
GenericArray<double> arr;
arr.IsEmpty() // check if it has valid ref
arr.assign(array_2d); //set reference to
然后使用某种模板逻辑
返回对数组的引用try{
boost::multi_array<double, 2>& array_2d_ref = arr.get<2>
//OR
boost::multi_array<double, 2>& array_2d_ref = arr.get<multi_array<double, 2>>
// First one look cleaner tho
}catch (ArrayDimentinalityMismatch e){
}
在相同的代码块中
arr.assign(array_3d);
try{
boost::multi_array<double, 2>& array_3d_ref=arr.get<multi_array<double, 3>>
}catch (ArrayDimentinalityMismatch e){
}
这可以使用模板吗?
答案 0 :(得分:2)
首先,我想你可能想评估你的设计。与仿函数一样,很少需要围绕泛型类型参数编写半刚性类型的包装器。
但是,如果您确实发现需要这个,那么这是一个使用boost::variant
的解决方案:
template <typename T>
struct GenericArray
{
template <size_t N> using array_t = boost::multi_array<T, N>;
template <typename Rhs> GenericArray& operator=(Rhs&& rhs) {
_storage = std::forward<Rhs>(rhs);
return *this;
}
template <size_t N> array_t<N> & get() { return boost::get<array_t<N> >(_storage); }
template <size_t N> array_t<N> const& get() const { return boost::get<array_t<N> >(_storage); }
private:
typename detail::make_generic_array_storage<T>::type _storage;
};
如果在运行时出现维度错误,get<>
成员函数会抛出boost::bad_get
异常。
现在,诀窍当然是_storage
的实施方式。我使用一些Boost MPL魔法在数组维度列表上生成一个变体:
namespace detail {
namespace mpl = boost::mpl;
template <typename T, size_t Mindim = 1, size_t Maxdim = 5>
struct make_generic_array_storage
{
template <size_t N> using array_t = boost::multi_array<T, N>;
template<typename N> struct to_array_f { typedef array_t<N::value> type; };
using list = typename mpl::transform<
mpl::range_c<size_t, Mindim, Maxdim>,
to_array_f<mpl::_1>,
mpl::back_inserter<mpl::vector<> >
>::type;
using type = typename boost::make_variant_over<list>::type;
};
}
如果你从高层看它,没有什么比这更复杂了:)
接下来:演示!看到 Live On Coliru
GenericArray<double> arr;
arr = array_3d;
try { auto& ref3 = arr.get<3>(); }
catch (boost::bad_get const& e) { std::cout << "L:" << __LINE__ << " " << e.what() << "\n"; }
try { auto& ref2 = arr.get<2>(); } // this fails
catch (boost::bad_get const& e) { std::cout << "L:" << __LINE__ << " " << e.what() << "\n"; }
arr = array_2d;
try { auto& ref2 = arr.get<2>(); } // this succeeds
catch (boost::bad_get const& e) { std::cout << "L:" << __LINE__ << " " << e.what() << "\n"; }
std::cout << "Done";
打印:
L:58 boost::bad_get: failed value get using boost::get
Done
正如所料。
奖金 :要在变体存储上实现更多类似数组的操作,请查看此处:
涉及此主题