Access variadic template argument of class X inside class Y<X>

Viewed 64

I have some graph classes that can inherit from each other to provide the functionality needed in different cases (directed graph, traversable graph, nested graph, etc).

In order to make it possible to use the final derived types, these are provided as template arguments to the base classes. This way, for instance Edge::GetSource can return the derived class Node, and not the base class Node.

To make things simple, the graph classes take only one template argument: GraphTypes. GraphTypes in turn takes as template arguments all the needed derived graph classes. This makes it very easy to make changes to the types used in the graph classes, as only GraphTypes need to be changed.

template<class GraphT, class NodeT, class EdgeT>
class GraphTypes {
public:
   using GraphType = GraphT;
   using NodeType = NodeT;
   using EdgeType = EdgeT;
}; // GraphTypes


template<class GraphTypes>
class Edge {
private:
   using GraphType = typename GraphTypes::GraphType;
   using NodeType = typename GraphTypes::NodeType;
   using EdgeType = typename GraphTypes::EdgeType;

public:
   NodeType &GetSource();

protected:
   NodeType *m_pSource;
}; // Edge


template<class GraphTypes>
inline NodeType &Edge<GraphTypes>::GetSource() {
   return *m_pSource;
} // Edge::GetSource

This is working great! But now I want to add an optional Context argument. In some cases, a context object needs to passed around while working on the graph and be made aware, for instance, when Edge::SetSource is called.

My idea is to add a variadic template argument. This way graph classes that need no context can just omit it. But how can I add a variadic template argument to GraphTypes and then use it inside the other graph classes that have GraphTypes as an template argument?

template<class GraphT, class NodeT, class EdgeT, class ...ContextT>
class GraphTypes {
public:
   // error C3520: 'ContextT': parameter pack must be expanded in this context
   using ContextType = ContextT;
}; // GraphTypes


template<class GraphTypes>
class Edge {
private:
   using ContextType = typename GraphTypes::ContextType;

public:
   // error C3543: 'GraphTypes::ContextType': does not contain a parameter pack
   void SetSource(NodeType &Source, ContextType &...Context);
}; // Edge


template<class GraphTypes>
void Edge<GraphTypes>::SetSource(NodeType &Source, ContextType &...Context) {
   if(&Source == m_pSource)
      return;
      
   // I think this should work, but open to suggestions ;)
   std::initializer_list<bool>{ (Context.PreSetSource(*this), true)... };

   m_pSource = &Source;

   std::initializer_list<bool>{ (Context.PostSetSource(*this), true)... };
} // Edge::SetSource
0 Answers
Related