00 //============================================================================
01 // Name        : rule0/main.cpp
02 // Author      : Simonas Saltenis
03 // Description : A bare-bones graph class using STL vector
04 //============================================================================
05 
06 #include <iostream>
07 #include <algorithm>
08 
09 class digraph_t
10 {
11 public:
12     struct edge_t
13     {
14         std::size_t id;         // Edge id
15         std::size_t v_from_id;  // Vertex from and to ids
16         std::size_t v_to_id;
17     };
18 
19 private:
20     std::vector<edge_t>  edges{};
21 
22 public:
23     digraph_t() = default;
24     explicit digraph_t(std::size_t init_size) { edges.reserve(init_size); };
25 
26     // Rule of zero  =  no special functions
27 
28     bool add_edge(const edge_t& e)    // most basic function to add an edge
29     {
30         try
31         { edges.push_back(e); }
32         catch(...)
33         { return false;       }
34 
35         return true;
36     };
37 
38     bool delete_edge (std::size_t e_id)    // most basic function to find and delete an edge
39     {
40         auto ep = std::find_if(std::begin(edges), std::end(edges),
41                                [e_id](const edge_t& e) { return e.id == e_id; });
42 
43         if (ep == std::end(edges)) return false;  // not found
44         *ep = edges.back();                   // move the last edge to the place of the deleted
45         edges.pop_back();
46         return true;
47     }
48 
49     friend std::ostream& operator<< (std::ostream& os, const digraph_t& g)
50     {
51         for (auto& e : g.edges)
52             os << '(' << e.id << ", " << e.v_from_id << ", " << e.v_to_id << ")\n";
53 
54         return os;
55     }
56 };
57 
58 digraph_t create_graph()
59 {
60     auto g = digraph_t{10};
61 
62     g.add_edge({0,0,1});
63     g.add_edge({1,1,2});
64 
65     auto gg = std::move(g);  // move constructor, just for fun as it is cheap :)
66 
67     gg.add_edge({2,2,3});
68     gg.add_edge({3,3,0});
69 
70     return gg;            // no move constructor due to NRVO (named return value optimization)
71 }
72 
73 int main()
74 {
75     auto g1 = create_graph();   // no move constructor due to copy elision
76     auto g2 = g1;               // copy constructor
77 
78     g1.delete_edge(1);
79 
80     std::cout << g1 << "---------\n";
81 
82     g1 = g2;   // copy assignment
83 
84     std::cout << g1 << "---------\n";
85 
86     digraph_t g2;
87     g2 = std::move(g1);  // move assignment
88 
89     // for fun, we can print g1: g1 should be in a valid state, but what it contains is undefined
90     std::cout << g1 << "---------\n";
91 
92     g1 = create_graph();  // also move assignment
93 
94     return 0;
95 }