0

I have two (really three, but one is irrelevant here) header files with classes in them for a project. One Node class that includes a set of pointers to other nodes (its like a tree), and the other class is a graph class (entitled AML) that holds a set of all the pointers to nodes in their respective layers.

I wanted to write my own C++ set operations (because I'll need them), so I decided to declare a namespace that has the set operation functions. However when I try to use these set operations in my Node class, I get an error. Here is the relevant code:

aml.h

#pragma once
#include <set>
#include "Node.h"
#include "constant.h"

using namespace std;
class aml
{
// class stuff
};

namespace setops {
    set<Node*> set_union(set<Node*>  &a, set<Node*>  &b);
    // other set operations
}

aml.cpp

#include "aml.h"

using namespace std;


//class functions

set<Node*> setops::set_union(set<Node*>  &a, set<Node*>  &b) {
    set<Node*> c;
    for (Node* data : a) {
        c.insert(data);
    }
    for (Node* data : b) {
        c.insert(data);
    }

    return c;
}

Node.h

#pragma once
#include <string>
#include <set>
#include "aml.h"
#include "constant.h"

using namespace std;
class Node
{
private:
    set<Node*> lower;
public:
    set<Node*> getLower();
    set<Node*> GL();
};

and here is the GL() method in which the error occurs. This is supposed to return the set of all nodes that can be reached by traveling down the tree. getLower() returns the lower set that houses all a node's children.

Node.cpp

#include "Node.h"

set<Node*> Node::getLower() {
    return this->lower;
}

set<Node*> Node::GL() {
    set<Node*> lowerSet;
    lowerSet.insert(this);
    if (this->lower.size() == 0) {
        return lowerSet;
    }
    set<Node*> recurse;
    for (Node* node : this->lower) {
        recurse = node->GL();
        lowerSet = setops::set_union(lowerSet, recurse); //This is the error line
    }
    return lowerSet;
}

I marked the problem line. It actually has three errors, one on each parameter and one of the equals sign. The errors say (all of them are pretty much the same, but this is the parameter one)

a reference of type "set::set<<error-type>*, std::less<<error-type>*>, std::allocator<<error-type>*>& "(non-const qualified) cannot be initialized with a value of type "set::set<Node*, std::less<Node*>, std::allocator<Node*>> "

I have no idea what is going on, any help appreciated!

E_net4
  • 27,810
  • 13
  • 101
  • 139
wjmccann
  • 502
  • 6
  • 18
  • Wild guess: There's no such thing as `setops::set_union()` because it's not not declared. Try moving `namespace setops` to another file, and include it in node.cpp. Let me know if that works. –  May 24 '19 at 19:12

1 Answers1

3

You have a circular dependency, node.h includes aml.h and vice versa. include aml.h after node.h into node.cpp.

Problem is that both headers have to be used together then , because one depends on another. And it is a sign of bad architecture.

Consider: 1) Forward declare Node in aml.h and keep using circular or merge headers together. 2) Making operations template functions. 3) Use of curiously recursive template for Node class 4) Combination of those.

Do not use using namespace in a header. It may cause problem for you or anyone else who uses your header, especially if you "play" with nested namespaces yourself. In worst case, you can write 'using std::set;' to use that one name explicitly.

Do you really need an std::set?

PS. In C++17 there is a merge method for std::set

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • 1
    Thank you! I moved the namespace into Node.h/Node.cpp, then I made Node.h no longer dependent on aml.h, since only aml uses Node and not vice versa. What do you mean by do I have to use an `std::set`? Is there a better way to represent sets or is that just overkill – wjmccann May 24 '19 at 19:35
  • @wjmccann depends! it's a sorted set. I don't know what's the purpose, if it's anything like red-black tree or similar where you again from sorting, then that's fine. – Swift - Friday Pie May 24 '19 at 19:38
  • 1
    Well its not really a tree, its kinda confusing, but I'm trying to implement this paper in C++: https://arxiv.org/abs/1803.05252. So I'm just using `std::sets` because I am familiar with them and I'm not sure whats the best data structure to use – wjmccann May 24 '19 at 19:42
  • @wjmccann I have to study that to even hazard a guess, but there is also `std::unordered_set`. Tbh, I'd wrote code so I could specialize it for different data structures. Choosing best structures or implementations sometimes requires experimenting. – Swift - Friday Pie May 24 '19 at 19:46