c++templatescrtptype-aliasclass-template

How to make type alias invisible to derived classes?


I have a set of base graph classes that use CRTP to work with the derived graph classes. I have a template class GraphTypes that take the derived graph classes as template parameters, and then the base graph classes, like Edge and Node, take GraphTypes as template parameter.

Inside the base graph classes, I use type aliases (using) to simplify using the derived classes. I would like these type aliases to only be visible inside the base graph classes, and not in the derived graph classes. Is this possible?

See the code below for the setup, and an issue where the type alias in the base graph class is being used in the derived class.

namespace DirectedGraph 
{
    template<class NodeT, class EdgeT>
    class GraphTypes 
    {
    public:
        using NodeType = NodeT;
        using EdgeType = EdgeT;
    };

    template<class GraphTypes>
    class Edge 
    {
    private:
        using NodeType = typename GraphTypes::NodeType;
        using EdgeType = typename GraphTypes::EdgeType;
    public:
        auto This() -> EdgeType&;
    };
}

namespace MyGraph
{
    class Node;
    class Edge;
    using GraphTypes = DirectedGraph::GraphTypes<Node, Edge>;

    enum class EdgeType { A, B, C };

    class Edge : public DirectedGraph::Edge<GraphTypes>
    {
        Edge(EdgeType Type); // `EdgeType` is interpreted as the type alias `DirectedGraph::Edge::EdgeType` instead of the enum `MyGraph::EdgeType`.
    };
}

Solution

  • I am assuming that you don't want to rename EdgeType in Edge. If you were willing to do that, you could just use different names for different aliases and not run into this issue.

    To solve this issue without changing any names, you can shadow DirectedGraph::Edge<T>::EdgeType by declaring another alias inside of MyGraph::Edge:

    class Edge : public DirectedGraph::Edge<GraphTypes> {
        // possibly make this private
        using EdgeType = MyGraph::EdgeType;
    
        // we could also use MyGraph::EdgeType directly here, but that would be uglier
        Edge(EdgeType Type);
    };
    

    The MyGraph::Edge::EdgeType alias will shadow any declarations in the scope of the base class and in the surrounding scope, so you can disambiguate like this.