我有一些代码会生成一组不同大小的tr1 :: array,但类型相同,比如
array<int, 2>
array<int, 4>
array<int, 6>
这些数组的数字及其大小是在编译时给出的,所以我确切地知道它们中有多少以及每个数据的大小(但它们可能不同)。
问题:我想将它们放在一个集合中(使用数组&lt;&gt;会很棒),但所有成员的类型必须相同,但事实并非如此。
我考虑过使用boost :: variant,但是如何使用编译时确定的类型列表来指定变量(我正在考虑预处理器的大量使用......)? 那么使用boost :: any呢?其他方法? (狂野指针?)
TIA 〜秋
更正:在这种情况下预处理器不可用。
答案 0 :(得分:3)
我会使用Boost的MPL和Fusion库。有两种方法可以结束类型列表:生成它们,或者明确定义它们。前者有点灵活,但很难说哪个适合你,因为我们不知道你如何得到你所拥有的价值。
无论如何,生成:
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <array>
#include <iostream>
namespace bmpl = boost::mpl;
// turns an index into an array
template <typename T>
struct make_array
{
// or whatever scheme you have
static const std::size_t size = T::value * 2;
// define generated type
typedef std::array<int, size> type;
};
// list of values to convert
typedef bmpl::range_c<size_t, 1, 10> array_range;
// transform that list into arrays, into a vector
typedef bmpl::transform<array_range, make_array<bmpl::_1>,
bmpl::back_inserter<bmpl::vector<>>
>::type array_collection;
或明确说明:
#include <boost/mpl/vector.hpp>
#include <array>
#include <iostream>
namespace bmpl = boost::mpl;
// list all array types
typedef bmpl::vector<
std::array<int, 2>,
std::array<int, 4>,
std::array<int, 6>,
std::array<int, 8>,
std::array<int, 10>,
std::array<int, 12>,
std::array<int, 14>,
std::array<int, 16>,
std::array<int, 18>
> array_collection;
无论哪种方式,您都可以像这样使用它:
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/mpl.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/mpl/for_each.hpp>
#include <typeinfo>
// fusion "fuses" the bridge between MPL and runtime
namespace bf = boost::fusion;
struct print_type
{
template <typename T>
void operator()(const T&) const
{
std::cout << typeid(T).name() << "\n";
}
};
struct print_values
{
template <typename T>
void operator()(const T& pArray) const
{
std::cout << "Printing array with size "
<< pArray.size() << ":\n";
std::for_each(pArray.begin(), pArray.end(),
[](int pX)
{
std::cout << pX << " ";
});
std::cout << std::endl;
}
};
int main(void)
{
// print all the types you have
bmpl::for_each<array_collection>(print_type());
std::cout.flush();
// make a usable type out of the typelist
typedef bf::result_of::as_vector<array_collection>::type array_fusion;
array_fusion arrays; // now have an array of different arrays,
// compile-time generated but run-time usable
// access like this:
bf::at_c<0>(arrays)[1] = 5;
bf::at_c<1>(arrays)[2] = 7;
bf::at_c<2>(arrays)[0] = 135;
// for_each:
bf::for_each(arrays, print_values());
}
答案 1 :(得分:0)
在STL容器中放置不同类型的类的唯一方法是,如果容器包含指针(引用不起作用,因为它们不是默认构造的)到某个基类型,并且要收集的对象都继承自那种类型。请注意,从基类继承的类型的容器(或任何模板类)不会从基类型的容器继承。你可以使用void *但你需要做很多丑陋和危险的演员,你必须记住自己释放记忆。为什么不编写一个固定大小的数组类,允许您在构造函数中设置大小?如果你写一个包装在araray周围,它不应该是太多的工作。如果你想使用一些基于智能指针的解决方案,不要试图使用auto_ptr,因为STL容器的复制语义是错误的 - 去像boost shared_ptr这样的东西。
答案 2 :(得分:0)
您没有说明为什么需要一组不同大小的静态大小的数组。这很奇怪。为什么不使用动态大小的数组?
您的选择是:
使用std :: vector而不是std :: tr1 :: array。
存储指向数组的指针以及集合中数组的大小。这可能类似于:std::vector<std::pair<int *, size_t> >
。只需确保数组的生命周期至少与向量的生命周期一样长!
我希望boost :: variant能够正常工作,但在实践中使用它会相当繁琐。
boost::variant<array<int, 2>, array<int, 4>, array<int, 6>, ... >