c++ 如何使类型别名对派生类不可见?

3vpjnl9f  于 2023-06-25  发布在  其他
关注(0)|答案(2)|浏览(154)

我有一组基本图形类,它们使用CRTP来处理派生图形类。我有一个模板类GraphTypes,它将派生的图类作为模板参数,然后基本图类,如EdgeNode,将GraphTypes作为模板参数。
在基类graph中,我使用类型别名(using)来简化派生类的使用。我希望这些类型别名只在基本图形类中可见,而在派生图形类中不可见。这可能吗?
请参阅下面的代码,了解设置,以及在派生类中使用基图类中的类型别名的问题。

  1. namespace DirectedGraph
  2. {
  3. template<class NodeT, class EdgeT>
  4. class GraphTypes
  5. {
  6. public:
  7. using NodeType = NodeT;
  8. using EdgeType = EdgeT;
  9. };
  10. template<class GraphTypes>
  11. class Edge
  12. {
  13. private:
  14. using NodeType = typename GraphTypes::NodeType;
  15. using EdgeType = typename GraphTypes::EdgeType;
  16. public:
  17. auto This() -> EdgeType&;
  18. };
  19. }
  20. namespace MyGraph
  21. {
  22. class Node;
  23. class Edge;
  24. using GraphTypes = DirectedGraph::GraphTypes<Node, Edge>;
  25. enum class EdgeType { A, B, C };
  26. class Edge : public DirectedGraph::Edge<GraphTypes>
  27. {
  28. Edge(EdgeType Type); // `EdgeType` is interpreted as the type alias `DirectedGraph::Edge::EdgeType` instead of the enum `MyGraph::EdgeType`.
  29. };
  30. }
o75abkj4

o75abkj41#

您始终可以限定完整的命名空间

  1. namespace MyGraph {
  2. class Node;
  3. class Edge;
  4. using GraphTypes = DirectedGraph::GraphTypes<Node, Edge>;
  5. enum class EdgeType { A, B, C };
  6. class Edge : public DirectedGraph::Edge<GraphTypes> {
  7. Edge(::MyGraph::EdgeType Type);
  8. // ^^^^^^^^^^^^^^^^^^
  9. // or
  10. // Edge(MyGraph::EdgeType Type);
  11. };
  12. }

或者为类型/类型别名使用不同的名称以避免混淆。
也就是说,如果您坚持保持名称不变,并且不想从基类中使用它们,请通过类/结构提供对这些别名类型的间接访问。

  1. namespace DirectedGraph
  2. {
  3. // ....
  4. template<class GraphTypes>
  5. class Edge {
  6. private:
  7. public:
  8. struct Internal { // moved under the Internal struct!
  9. using NodeType = typename GraphTypes::NodeType;
  10. using EdgeType = typename GraphTypes::EdgeType;
  11. };
  12. auto This() -> typename Internal::EdgeType&;
  13. };
  14. }
  15. namespace MyGraph {
  16. // ....
  17. enum class EdgeType { A, B, C };
  18. class Edge : public DirectedGraph::Edge<GraphTypes> {
  19. Edge(EdgeType Type); //Now you can!
  20. };
  21. }

Demo

展开查看全部
rm5edbpk

rm5edbpk2#

我假设你不想在Edge中重命名EdgeType。如果你愿意这样做,你可以使用不同的别名不同的名字,而不会遇到这个问题。
为了解决这个问题而不更改任何名称,您可以通过在MyGraph::Edge中声明另一个别名来隐藏DirectedGraph::Edge<T>::EdgeType

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

MyGraph::Edge::EdgeType别名将遮蔽基类作用域和周围作用域中的所有声明,因此您可以像这样消除歧义。

相关问题