不能将 CRTP 用于内部类

use*_*083 0 c++ templates crtp

我正在尝试使用 CRTP 来实现多种迭代器类型的通用功能。如此处 使用带有 CRTP 的内部类所述,不可能将 CRTP 用于内部类,因此我将基本迭代器类移出容器类,并在迭代器的容器内继承它。但我还是得到了

error: invalid use of incomplete type 'class ConcreteIteratorBase<Node<int>, std::iterator_traits<Node<int>*>, std::iterator<std::forward_iterator_tag, Node<int>, long int, Node<int>*, Node<int>&> >'
Run Code Online (Sandbox Code Playgroud)

错误。

这是最小的可重现示例:

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <type_traits>
#include <utility>

template <typename T>
class NotEqFromEqMixin : public T
{
public:
  bool operator!=(T const & other) const
  {
    return !(static_cast<T const &>(*this) == other);
  }
};

template <typename Iterator, typename Traits, typename StdBase>
class IteratorHelperMixin : public NotEqFromEqMixin<Iterator>, public StdBase
{
public:
  using pointer = typename Traits::pointer;
  using reference = typename Traits::reference;

  pointer operator->()
  {
    return &**this;
  }
};

template <typename NodeT, typename TraitsT, typename StdBaseT>
class ConcreteIteratorBase
  : public IteratorHelperMixin<ConcreteIteratorBase<NodeT, TraitsT, StdBaseT>, TraitsT, StdBaseT>
{
public:
  using Super = IteratorHelperMixin<ConcreteIteratorBase<NodeT, TraitsT, StdBaseT>, TraitsT, StdBaseT>;
  using typename Super::pointer;
  using typename Super::reference;

  ConcreteIteratorBase(pointer node) : node(node) {}

  reference operator*() noexcept { return *node; }

  bool operator==(ConcreteIteratorBase const & other) const noexcept { return node == other.node; }

protected:
  pointer node;
};

template <typename Value>
class Node
{
public:
    ~Node() { delete next; }


    Node* next = nullptr;
    Value value;
};

template <typename Value>
class List
{
public:
    using NodeType = Node<Value>;

    void push(Value value)
    {
        NodeType* newNode = new NodeType();
        newNode->value = value;
        newNode->next = head;
        head = newNode;
    }

    class iterator :
        public ConcreteIteratorBase<
            Node<Value>,
            std::iterator_traits<Node<Value>*>,
            std::iterator<std::forward_iterator_tag, Node<Value>>
        >
    {
        using Super = ConcreteIteratorBase<
            Node<Value>,
            std::iterator_traits<Node<Value>*>,
            std::iterator<std::forward_iterator_tag, Node<Value>>
        >;
        
        public:
        iterator(NodeType* ptr = nullptr) : Super(ptr){}

        iterator& operator++()
        {
            if (this->node)
            {
                this->node = this->node->next;
            }
            return *this;
        }

        Value& operator*()
        {
            return this->node->value;
        }

        bool operator==(const iterator& other) const
        {
            return this->node == other.node;
        }
    };

    iterator begin()
    {
        return iterator{head};
    }

    iterator end()
    {
        return iterator{};
    }

    NodeType* head = nullptr;
};


int main(int , char**)
{
    List<int> list;
    for (int i = 0; i < 10; ++i)
    {
        list.push(i);
    }

    for(auto & val : list)
    {
        std::cout << val << " ";
    }
    std::cout << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Jar*_*d42 5

你的问题是你在进行循环继承时滥用了 CRTP:

ConcreteIteratorBase
-> IteratorHelperMixin<ConcreteIteratorBase, ..>-> NotEqFromEqMixin<ConcreteIteratorBase>
->ConcreteIteratorBase

你应该放弃这里的继承

template <typename T>
class NotEqFromEqMixin //: public T
//                     ^^^^^^^^^^^^
{
public:
  bool operator!=(T const & other) const
  {
    return !(static_cast<T const &>(*this) == other);
  }
};
Run Code Online (Sandbox Code Playgroud)

演示