Is there any library anyone knows of which allows arbitrarily deep nested arrays in C++ similar to how PHP handles it?
Is there any library anyone knows of which allows arbitrarily deep nested arrays in C++ similar to how PHP handles it?
You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.
C++ supports nested arrays far deeper than could be reasonably practical. What exactly are you trying to do? And for those of us that don't know PHP, can you clarify how "PHP handles it"?
My best code is written with the delete key.
You mean the ability to make any variable an array? For the rest of you, PHP is very loosely typed, so you can do things like
You can't do that in C++, because the syntax enforces strong typing. You cannot change the type of a variable at runtime.PHP Code:
var $x = 'abc';
$x = array(1, 2, 3);
$x[0] = array($foo, $bar);
But in C++, you CAN do things like
Code:int multidimensional_array[10][10][10][10][10]; //declares a 5-dimensional array multidimensional_array[2][3][4][5][6]; //one element multidimensional_array[9][9][9][9]; //int* pointing to the last row
Code:#include <stdio.h> void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){ puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9 /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i] ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][ t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}
Apologies. I meant an array whose elements can be either a string or a deeper array. For example, in PHP you could have an array like this:Originally Posted by Prelude
array[0] = "Hello";
array[1][0] = "Hi";
array[1][1] = "Bye";
where the first element of array is a string, and the second element is another array.
The nice features are visual appeal in the code and savings in storage -- for example if one set a maximum depth of 10 in C++, then you could do:
array[0][0][0][0][0][0][0][0][0][0] = "Hello";
array[1][0][0][0][0][0][0][0][0][0] = "Hi";
array[1][1][0][0][0][0][0][0][0][0] = "Bye";
but that both makes the code less readable and wastes space.
I am pretty sure I could write some class that could do this but I don't care to reinvent the wheel if it's been done.
Application -- I want a treelike data structure to facilitate manipulating files that are treelike in nature. By that I mean each node can contain data (leaves) as well as other subnodes.
I'm not married to the nested array approach, any sensible solution would be great. An example of a treelike data structure might be the windows registry, where each registry key can contain both data elements as well as subkeys. Or the filesystem itself, directories can contain files as well as subdirectories.
Last edited by Cat; 06-09-2006 at 03:46 AM.
You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.
You might be looking to use something like a std::vector of boost::any.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
boost::variant might be more appropriate, I think, if you know the types beforehand.
I have implemented similar things using the Composite pattern and polymorphism, but I don't know of any existing generic implementations. If the datatype is always the same (e.g. string) you wouldn't really need the polymorphism part.
Also, it sounds like how XML is structured, so you might consider looking at implementations of XML data storage to see if anything fits your needs.
Here's a quick version of how I might implement it for fun, others can critique or improve if you want to consider using it.
Code:#include <vector> template <typename T> class Node { typedef std::vector<Node<T> > SubnodeList; public: typedef typename SubnodeList::size_type size_type; typedef typename SubnodeList::const_iterator const_iterator; typedef typename SubnodeList::iterator iterator; Node() : data_(), has_data_(false) { } explicit Node(const T& data) : data_(data), has_data_(true) { } void set_data(const T& data) { data_ = data; has_data_ = true; } const T& get_data() const { return data_; } bool has_data() const { return has_data_; } void push_back(const Node& node) { subnodes_.push_back(node); } size_type size() const { return subnodes_.size(); } const Node& operator[](size_type index) const { return subnodes_[index]; } Node& operator[](size_type index) { return subnodes_[index]; } const_iterator begin() const { return subnodes_.begin(); } const_iterator end() const { return subnodes_.end(); } iterator begin() { return subnodes_.begin(); } iterator end() { return subnodes_.end(); } private: SubnodeList subnodes_; T data_; bool has_data_; // maybe necessary, maybe not?? }; #include <ostream> template <typename T> std::ostream& print_node(std::ostream& out, const Node<T>& node) { if (node.has_data()) out << node.get_data() << ' '; if (node.size() == 0) return out; out << "[ "; for (Node<T>::const_iterator cur_node = node.begin(); cur_node != node.end(); ++cur_node) { print_node(out, *cur_node); } out << "] "; return out; } #include <iostream> #include <string> int main() { Node<std::string> root; root.push_back(Node<std::string>("0")); root.push_back(Node<std::string>("1")); root.push_back(Node<std::string>("2")); root[0].push_back(Node<std::string>("zero")); root[0].push_back(Node<std::string>("zilch")); root[1].push_back(Node<std::string>("one")); root[1].push_back(Node<std::string>("uno")); root[1].push_back(Node<std::string>("0x01")); root[2].push_back(Node<std::string>("two")); root[2].push_back(Node<std::string>("due")); print_node(std::cout, root); std::cout << '\n' << root[1][2].get_data() << '\n'; }