一对int可以声明为:std::pair<int, std::pair<int, int> > A;
类似地,一对int作为std::pair<int, std::pair<int, std::pair<int, int> > >A;
我想宣布一个任意的";成对的";在我的代码中。即,根据某个值(仅在运行时已知(,我想要一对int(n = 1
(或一对int对(n = 2
(等等。我想知道如何在C++中有效地做到这一点吗?
以下是Python中的一段代码:
import numpy as np
n = 4 # a value known at runtime
m = 2 # a value known at runtime
def PP(A, j):
A_s = []
if j == n-1:
for i in range(1, m):
A_s.append((i, A[i]))
else:
for i in range(1, m):
A_c = A[i]
A_s.append((i, PP(A_c, j+1)))
return A_s
j = 0
# The dimension of A is known at runtime.
# Will have to create np.ones((m, m, m, m, m)) if n = 5
A = np.ones((m, m, m, m))
B = PP(A, 0)
与Python不同,C++是一种静态类型的语言。因此,如果要存储的内容的结构或大小直到运行时才知道,则不能像嵌套对一样使用类型本身来描述特定的结构。相反,您所做的是使用可以动态调整大小的C++类型。也就是说,std::vector<int>
是在C++中存储动态整数的惯用且有效的方法。
如果您真的想要像Python示例([(1, [(1, [(1, [(1, 1.0)])])])]
(中那样的树状结构,那么这在C++中也是可能的。但这需要更多的工作。例如参见C++中的二进制树:第1部分。
C++(参见本网站和n3337,C++11标准草案(同时具有std::variant
和std::optional
(在C++17中(。似乎您想要一些标记的并集(如C++编译器中的抽象语法树(和智能指针(例如std::unique_ptr
(。
也许你想要类似的东西
class Foo; // forward declaration
class Foo {
std::variant<std::unique_ptr<Foo>, std::pair<int,int>> fields;
/// many other things, in particular for the C++ rule of five
};
与Python相反,每个C++值都有一个已知的类型
您可以巧妙地将两者结合起来,并且可能对其他标准容器(特别是std::vector
(感兴趣。请阅读一本好的C++编程书籍,并注意五条规则。
从github或gitlab上的现有开源软件(如Qt、RefPerSys、Wt、Fish、Clang静态分析仪、GCC和许多其他(中获得灵感
还请阅读C++编译器(如GCC(和调试器(如GDB(的文档。如果您使用最近的GCC,请使用所有警告和调试信息进行编译,例如g++ -Wall -Wextra -g
。通过编写编码约定进行文档记录,对于足够大的代码库,可以考虑编写GCC插件来强制执行它们。最近的GCC(2020年10月的GCC 10(有一些有趣的静态分析选项,你可以试试。
考虑在C++代码库中使用Clang静态分析器(另请参阅本报告草案、DECODER和CHARIOT欧洲项目以及MILEPOST GCC(。
也可以阅读最近ACM SIGPLAN会议上关于C++的论文。
您也可以定义class Matrix
,或者使用提供它们的现有库(例如boost(,也许可以将这个答案调整为C++。
请记住,每个C++类型的sizeof
在编译时都是已知的。AFAIK、C++没有任何灵活的数组成员(就像C一样(。
正如其他人已经说过的,你不能这样做。至少在运行时不会。
然而,总的来说,它似乎也没有用处。假设您有以下类型(与您的类型类似,但在编译时具有已知的嵌套级别(,并声明该类型的对象
using your_type = std::pair<int, std::pair<int, std::pair<int, int>>>
your_type obj1{1,{2,{3,4}}};
这与没有什么不同
std::array<int,4> obj2{1,2,3,4};
你的信件在哪里:
obj1.first == obj2[0]
obj1.second.first == obj2[1]
obj1.second.second.first == obj2[2]
obj1.second.second.second == obj2[3]
为了强调它们实际上是一样的,请考虑如何为这样的类型实现size
函数;它可能是这样的元函数(可能有更好的方法(:
template<typename T, typename Ts>
constexpr int size(std::pair<T,Ts>) {
if constexpr (std::is_same_v<T,Ts>)
return 2;
else
return 1 + size(Ts{});
}
换句话说,它们是同构的。
现在,您的要求是以这样一种方式编写your_type
,即在运行时已知嵌套级别。如前所述,这是不可能的,但猜猜与你想象的类型同构是什么?std::vector<int>
!
所以我的答案是:你不需要;只需使用std::vector
即可。
最后,根据我的回答,如果真的想要一个行为像任意嵌套对的类型,那么你可以在std::vector
周围写一个包装器,这似乎是合理的。但我不明白为什么你真的需要这么做。