4

Someone suggested here using tuples instead of all public structures. And I found it useful. But my problem is now with the following section:

using Edge = std::tuple<Node_wp,//From Node
                        Node_wp>;//To Node
using Edge_wp = std::weak_ptr<Edge>;

using Node = std::tuple<std::vector<Edge_wp>,//Incoming Edges
                        std::vector<Edge_wp>>;//Outgoing Edges
using Node_wp = std::weak_ptr<Node>;

How can I overcome this circular dependency in template parameters. Forward declaration (with the knowledge in my possession) won't work since type Edge is can not be formed without knowing type Node and visa versa.

Obviously I can make one of them struct and be done with it. But it will be ugly to break symmetry in access.

ifyalciner
  • 1,190
  • 1
  • 10
  • 22
  • 2
    didnt read the linked answer, but I disagree with the premise, just prefer structs over tuples. If your edge connects `Node_wp`s then why not declare it as such? Also `from_node` and `to_node` would be much better names than `first` and `second` – 463035818_is_not_an_ai Oct 16 '17 at 09:56
  • @tobi303 They suggest using 'enum's for readability. But real catch here is not implementing member functions (sorting, equality, serialization etc.) which are already part of 'tuple' (or libraries supporting tuple). – ifyalciner Oct 16 '17 at 10:02

1 Answers1

5

You can use struct and public inheritance to fix your circular dependency issue. Node will become a struct wrapper around an std::tuple:

#include <memory>
#include <tuple>
#include <vector>

struct Node;
using Node_wp = std::weak_ptr<Node>;

using Edge = std::tuple<Node_wp,  // From Node
                        Node_wp>; // To Node
using Edge_wp = std::weak_ptr<Edge>;

struct Node : std::tuple<std::vector<Edge_wp>, // Incoming Edges
                         std::vector<Edge_wp>> // Outgoing Edges
{
    using std::tuple<std::vector<Edge_wp>, std::vector<Edge_wp>>::tuple;
}; 
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • This is perfect. Thank you. – ifyalciner Oct 16 '17 at 10:07
  • @ifyalciner Why did this answer get accepted? This is actually the same as initially proposed solution: "Obviously I can make one of them struct". – user7860670 Oct 16 '17 at 10:22
  • 1
    @VTT what I meant was using struct as itself (I couldn't think of using inheritance to break circle). Now struct wrapper is just a shallow cover over tuple. And I can use it as tuple. But if you have other suggestions instead of inheritance I would like to hear as well. – ifyalciner Oct 16 '17 at 10:26
  • 1
    @VTT: this technique still exposes `std::tuple`'s interface. The OP mentioned `struct`, but not inheritance: therefore I (rightly) assumed that he/she didn't consider public inheritance and was just referring to a "traditional" `struct`. – Vittorio Romeo Oct 16 '17 at 10:30