cstdarg question

Hello there folks,

've got a question related to "variadic arguments" (defined in cstdarg or stdarg.h). Here's my code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <string>
#include <stdarg.h>
#include <vector>

class CNode
{
private:
    std::string Name;
    std::vector<CNode> Children;
public:
    CNode(std::string s,unsigned population,...):
            Name(s)
    {   va_list vl;
        va_start(vl,population);
        for(int i = 0; i < population; i++)
            Children.push_back(va_arg(vl,CNode));
        va_end(vl);
    }
    
    ~CNode() {}
    
    void DisplayTree() const
    {   std::cout << Name << std::endl;
        for(int i = 0; i < Children.size(); i++)
        {
            std::cout << "- " << Children[i].Name << std::endl;
        }
    }
    
    unsigned GetChildrenAmount() const {return (Children.size());}
};

int main()
{
    CNode Tree("Master",2,
            CNode("Slave",0),
            CNode("Slave",0)
            );
    Tree.DisplayTree();
}

What this is supposed to output is:
Master
- Slave
- Slave

But it refuses to run properly, it gives me a "Illegal instruction"-runtime error. What am I doing wrong here?
It seems that you cannot pass non-POD types to ...
With gcc I get this warning:
warning: cannot receive objects of non-POD type 'class CNode' through '...'; call will abort at runtime|
Last edited on
At lines 17 and 39:
warning: cannot pass objects of non-POD type 'class CNode' through '...'; call will abort at runtime

EDIT: Dammit.

-Albatross

Last edited on
POD stands for Plain Old Data - that is, a struct (or class) with no members except data members. Wikipedia goes into a bit more detail and defines a POD in C++ as "A Plain Old Data Structure in C++ is an aggregate class that contains only PODS as members, has no user-defined destructor, no user-defined copy assignment operator, and no nonstatic members of pointer-to-member type."
So if I'd create external functions, instead of member functions, everything is going to work?
Nevermind, vectors and strings aren't PODs. .. Damnit.
Last edited on
I almost find it's silly that they didn't update certain C libraries in C++ to use C++ features.

-Albatross
Last edited on
Yeah. :/
Why update a feature from the C language that is patently unsafe? There are much safer ways to accomplish the same thing. Variadic functions should be no more than a curiosity for intermediate C++ programmers. You only need to learn what it does so you know how to refactor it.

Pass a container to the CNode constructor instead.

I agree that instead one should pass a sequential container of arguments to the CNode constructor, however... ah. That's why they didn't update variadic functions. It's a waste of effort.

Disregard my previous statement.

-Albatross
Last edited on
Not entirely unrelated, but fun goofiness anyway:
http://www.cplusplus.com/forum/beginner/18489/
You could also use operators for your CNode class to add peers and children. I did something like this for a toy XML DOM builder in C++.

1
2
3
4
5
6
7
    document doc();
    doc =+ element("Book")
            / element("Title") = "Apollo 13"
            + (element("Author") = "Buzz Aldrin"
                + attribute("Primary") = "yes")
            + element("Publisher") = "Doubleday"
            + element("Year") = "1999";

Results in:

<Book>
<Title>Apollo 13</Title>
<Author Primary="yes">Buzz Aldrin</Author>
<Publisher>Doubleday</Publisher>
<Year>1999</Year>
</Book>


"+" adds a peer node and "/" adds a child node.
Got my code to work :D :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
#include <vector>

class CNode
{
private:
    std::string Name;
    std::vector<CNode> Children;
public:
    CNode(std::string s) : Name(s) {}
    ~CNode() {}

    CNode& operator+(const CNode& n)
    {
        Children.push_back(n);
        return *this;
    }

    void DisplayTree(unsigned x = 0) const
    {   for(unsigned xx = 0; xx < x; xx++) std::cout << "-";
        std::cout << Name << std::endl;
        for(int i = 0; i < Children.size(); i++)
        {
            if (Children[i].GetChildrenAmount())
            {
                Children[i].DisplayTree(x+1);
            }
            else
            {
                for(unsigned xx = 0; xx < (x+1); xx++) std::cout << "-";
                std::cout << Children[i].Name << std::endl;
            }
        }
    }

    unsigned GetChildrenAmount() const {return (Children.size());}
};

int main()
{
    CNode Tree("Master");
    Tree
        +(CNode("Slave")
            +CNode("Dog")
            +CNode("Rat"))
        +CNode("Slave");
    Tree.DisplayTree();
}

Just one thing, how do I check whether a tree contains recursive declarations (on any level)?
I'm willing to bet there's a more efficient algorithm for this that I don't know about, but here's one way to do it. Keep track of the size of the tree. To check for loops, attempt to iterate over all the nodes, counting the nodes you've visited. If the iteration count exceeds the size of the tree, you've got a loop somewhere.
Topic archived. No new replies allowed.