C++与 Java 一样?:具有 *可变* 长度 int 的向量的向量

发布于 2024-08-11 06:39:26 字数 358 浏览 8 评论 0 原文

我的模型最好使用一些

v int[30][i][N_i];

由 30 个整数元组向量组成的结构,其中

v[0] 是一个虚拟值,
v[1] 是普通整数(其中 N_0 个),
v[2] 是 int 对(N_1 对)
...
v[29] 将是 29 个 int 元组(其中 N_29 个),

不是 vector> 就像“generic-vector-of-显然

,外部的固定dim=30是没有问题的,内部的由自扩展的STL向量类来处理。

有没有办法让中间尺寸固定,但不是恒定的?

My model would best use some

v int[30][i][N_i];

structure that is 30 vectors of tuples of ints, where

v[0] is a dummy,
v[1] are plain ints (N_0 of them),
v[2] are pairs of int (N_1 pairs)
...
v[29] would be 29-tuples of int (N_29 of them)

This is not vector<vector<int>> like in "generic-vector-of-vectors-in-c"

Apparently, the outer fixed dim=30 is no problem, the inner one is taken care of by the self-extending STL vector class.

Is there any way to get the middle dimension fixed, but not constant?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

花之痕靓丽 2024-08-18 06:39:26

正如我在对你的问题的评论中所写的那样,我不确定你在寻找什么(顺便说一句,我对“as in Java”部分非常感兴趣)。

但因为我认为看看如何使用 Boost 生成它会很有趣。MPL(和融合...和数组< /a>),我假设您想要一个静态定义的结构,其 Ntn 元素是大小为 N 的 int 数组的向量:

#define FUSION_MAX_VECTOR_SIZE 30

#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/inserter.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/size_t.hpp>

#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/as_vector.hpp>

#include <boost/array.hpp>

#include <vector>


namespace bf = boost::fusion;
namespace bmpl = boost::mpl;

// Type generator used for elements 2..N
// For those elements, the type of the n'th element is
// std::vector<boost::array<int, n>>
template<class SizeT>
struct VectorOfArray
{
    typedef std::vector<boost::array<int, SizeT::type::value> > type;
};

// The dummy type used for the first element
struct Dummy{};

// The container itself
template<size_t Size>
struct StrangeContainer
{

    // Define a fusion::vector (this is, more or less, equivalent to a tuple)
    // of "Size" elements, where:
    // - the type of element 0 is Dummy, 
    // - the type of element 1 is vector<int>
    // - the type of the n'th element is vector<array<int, n>>
    typedef typename bf::result_of::as_vector<
        typename bmpl::transform<
            bmpl::range_c<size_t, 2, Size>,
            VectorOfArray<bmpl::_1>,
            bmpl::back_inserter<
                bmpl::vector<Dummy, std::vector<int> >
            >
        >::type
    >::type ContentsType;

    // Helper struct to compute the return type of the "At()" member
    template<size_t I>
    struct ElemType
    {
        typedef typename VectorOfArray<bmpl::size_t<I> >::type type;
    };

    // Specialize "At()"'s return type for element 1
    template<>
    struct ElemType<static_cast<size_t>(1)>
    {
        typedef std::vector<int> type;
    };

    // Specialize "At()"'s return type for element 0
    template<>
    struct ElemType<static_cast<size_t>(0)>
    {
        typedef Dummy type;
    };

    // Get the I'th element
    template<size_t I>
    typename ElemType<I>::type& 
    At()
    {
        return bf::at_c<I>(m_Contents);
    }

    // The fusion vector holding the elements
    ContentsType m_Contents;
};

int main()
{
    StrangeContainer<30> s;
    Dummy& d = s.At<0>();
    s.At<1>().push_back(1);
    s.At<2>().push_back(boost::array<int, 2>());
    s.At<3>().push_back(boost::array<int, 3>());
    s.At<29>().push_back(boost::array<int, 29>());
    s.At<29>()[0][0] = 1234;

    return 0;
}

As I wrote in a comment to your question, I'm not sure to understand what you are looking for (and I'm very interested by the "as in Java" part, BTW).

But since I thought it would be fun to see how it could be generated with Boost.MPL (and Fusion... and Array), I'm assuming that you want a statically defined structure whose Ntn element is a vector of int arrays of size N:

#define FUSION_MAX_VECTOR_SIZE 30

#include <boost/mpl/transform.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/inserter.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/size_t.hpp>

#include <boost/fusion/include/mpl.hpp>
#include <boost/fusion/include/at_c.hpp>
#include <boost/fusion/include/as_vector.hpp>

#include <boost/array.hpp>

#include <vector>


namespace bf = boost::fusion;
namespace bmpl = boost::mpl;

// Type generator used for elements 2..N
// For those elements, the type of the n'th element is
// std::vector<boost::array<int, n>>
template<class SizeT>
struct VectorOfArray
{
    typedef std::vector<boost::array<int, SizeT::type::value> > type;
};

// The dummy type used for the first element
struct Dummy{};

// The container itself
template<size_t Size>
struct StrangeContainer
{

    // Define a fusion::vector (this is, more or less, equivalent to a tuple)
    // of "Size" elements, where:
    // - the type of element 0 is Dummy, 
    // - the type of element 1 is vector<int>
    // - the type of the n'th element is vector<array<int, n>>
    typedef typename bf::result_of::as_vector<
        typename bmpl::transform<
            bmpl::range_c<size_t, 2, Size>,
            VectorOfArray<bmpl::_1>,
            bmpl::back_inserter<
                bmpl::vector<Dummy, std::vector<int> >
            >
        >::type
    >::type ContentsType;

    // Helper struct to compute the return type of the "At()" member
    template<size_t I>
    struct ElemType
    {
        typedef typename VectorOfArray<bmpl::size_t<I> >::type type;
    };

    // Specialize "At()"'s return type for element 1
    template<>
    struct ElemType<static_cast<size_t>(1)>
    {
        typedef std::vector<int> type;
    };

    // Specialize "At()"'s return type for element 0
    template<>
    struct ElemType<static_cast<size_t>(0)>
    {
        typedef Dummy type;
    };

    // Get the I'th element
    template<size_t I>
    typename ElemType<I>::type& 
    At()
    {
        return bf::at_c<I>(m_Contents);
    }

    // The fusion vector holding the elements
    ContentsType m_Contents;
};

int main()
{
    StrangeContainer<30> s;
    Dummy& d = s.At<0>();
    s.At<1>().push_back(1);
    s.At<2>().push_back(boost::array<int, 2>());
    s.At<3>().push_back(boost::array<int, 3>());
    s.At<29>().push_back(boost::array<int, 29>());
    s.At<29>()[0][0] = 1234;

    return 0;
}
爱要勇敢去追 2024-08-18 06:39:26

完成您想要的操作的最佳方法是围绕向量访问器编写包装函数。包装现有行为的最佳方法是编写一个新类,该类是用您喜欢的向量或向量来实现的。

The best way to do what you want is write wrapper functions around the vector accessors. The best way to wrap existing behavior is to write a new class that is implemented with your fancy vector of vector of what ever.

万水千山粽是情ミ 2024-08-18 06:39:26

我是 Michael(最初作者),现在的 ID 是 La-AIDA

首先,谢谢大家,Boost & 。融合对我来说很新鲜。

致埃里克:
一个错字:v[1] 应该有 N_1 个条目,v[2] N_2 等等。
我想要类似 STL 的东西,而不是 C 数组(缺少边界检查,无法添加它)。

对埃里克的新评论:
我尝试了你的解决方案,它立即起作用了(几乎在删除虚拟查询后)!
谢谢你!
但是:我需要类似的东西

 for (i = 1;i < 30;i++) {
    cout << s.At<i>[0] << endl; 
 }

,即 At<...> 的索引。应该是可变的(这就是重点,能够运行索引而不是单独处理 30 个硬编码的东西)
但 gcc 抱怨错误: 'i' 不能出现在常量表达式中

关于“as in Java”:
AfaIk,Java 中的二维矩阵不是什么
int v[10][10];
具有固定尺寸,但类似
int[][] v;
你首先有一个

v = new int[10][];

(或类似的语法),然后,这就是要点:

v[0] = new int[1];
...
v[9] = new a[10];

它形成一个三角矩阵,或者当然是你喜欢的任何形式。
事实上,常规的 10×10 矩阵也需要 1 加 10 个新矩阵。

关于结构本身:
是一个等效的数据结构

vector<int> v1;
vector<pair<int,int>> v2;
vector<int,int,int> v3;
...
vector<int[29]> v29;

然而,我们必须分别处理这 30 个部分中的每一个部分,这

。我希望能够说 v[5][3][123] = 99;
将第 123 个 5 元组中的第三个分量设置为 99,没有定义

vector<int> v[30][30];

哪个可以解决问题,但浪费了巨大的空间,因为
v[1][2..30][0..\infty] 或更一般的 v[i][i+1..30][*] 永远不会被使用。

所以,在我的问题中,我有一个 int 列表,另一个列表对,三元组,...,30 个 int 元组,所有这些都应该在单个结构内进行排序等,而不浪费空间。

I'm Michael (the initial author) now having ID La-AIDA

Firstly, thank you all, Boost & Fusion where new to me.

To Éric:
One Typo: v[1] should have N_1 entries, v[2] N_2 and so forth.
I would like STL-like stuff, not C-arrays (lacking bounds check with no option to add it).

New comment to Éric:
I tried your solution, it worked (almost, after removing the dummy query) immediately!
Thank you!
But: I need something like

 for (i = 1;i < 30;i++) {
    cout << s.At<i>[0] << endl; 
 }

that is, the index for At<..> should be variable (that is the whole point, to be able to run an index instead of treating 30 hard-coded things separately)
but gcc complains with error: 'i' cannot appear in a constant-expression

About the "as in Java":
AfaIk, a two-dim matrix in Java is not some
int v[10][10];
with fixed dimensions, but something like
int[][] v;
where you first have a

v = new int[10][];

(or similar syntax) and then, and this is the point:

v[0] = new int[1];
...
v[9] = new a[10];

which makes a triangular matrix, or of course any form you like.
In fact a regular 10-by-10 matrix as well requires 1 plus 10 new's.

About the structure itself:
An equivalent data structure would be

vector<int> v1;
vector<pair<int,int>> v2;
vector<int,int,int> v3;
...
vector<int[29]> v29;

where however we would have to address each of the 30 parts separately.

I would like to be able to say v[5][3][123] = 99;
to set the 3rd component in the 123rd 5-tuple to 99, without defining

vector<int> v[30][30];

which would do the trick, but wasting enormous space, since
v[1][2..30][0..\infty] or more generally v[i][i+1..30][*] are never used.

So, in my problem, I have a list of int's , another of pairs, of triples,..., of 30-tuples of int's, which all should be sortable etc., within a single structure, without wasting space.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文