C++ 模板化类给出 `error: non-template X used as template`

标签 c++ c++11 templates

<分区>

问题是为什么这段代码不能编译,特别是为什么我会得到一些奇怪的编译错误,比如

error: non-template ‘C_Iterator’ used as template

#include <type_traits>  // fot std::enable_if
#include <iostream>

template <class T>
struct Container{

  template <bool Is_Const>
  struct C_Iterator{

    using value_type        = T;
    using pointer           = T*;
    using reference         = T&;
    using difference_type   = std::ptrdiff_t;
    using iterator_category = std::random_access_iterator_tag;

    T* p;

    // args c-tors
    C_Iterator(T *p_): p(p_) {}
    // Copy
    C_Iterator(const C_Iterator<Is_Const>& other) = default;

    template<bool Was_Const, class = typename std::enable_if<Is_Const || !Was_Const>::type>
    C_Iterator(const C_Iterator<Was_Const>& other) : p{other.p}{}

    C_Iterator &operator=(const C_Iterator &other){
        p = other.p;
        return *this;
    }

    reference operator*() {return *p;}

    // some other stuff here
  };

  using iterator = C_Iterator<false>;
  using const_iterator = C_Iterator<true>;

  Container(T v) { storage = new int[1]; storage[0]=v; }
  ~Container() { delete storage;  }

  inline iterator       begin()       { return iterator(storage);}
  inline const_iterator begin() const { return const_iterator(storage);}

  T* storage;

};


template <class T>
struct Iterable_Wrapper{

  template <bool Is_Const>
  struct W_Iterator{

    using value_type        = T;
    using pointer           = T*;
    using reference         = T&;
    using iterator_category = std::forward_iterator_tag;

    using c_iterator = typename Container<T>::C_Iterator<Is_Const>;

    c_iterator it;

    // args c-tors
    W_Iterator( c_iterator it_ ): it(it_) {}

    // Copy
    W_Iterator(const W_Iterator<Is_Const>& other) = default;

    template<bool Was_Const, class = typename std::enable_if<Is_Const || !Was_Const>::type>
    W_Iterator(const W_Iterator<Was_Const>& other) : it{other.it}{}

    W_Iterator &operator=(const W_Iterator &other){
        it = other.it;
        return *this;
    }

    reference operator*() {return *it;}

    // some other stuff here
  };

  using iterator = W_Iterator<false>;
  using const_iterator = W_Iterator<true>;

  Iterable_Wrapper(T v) : wrapped_container(v) {}
  ~Iterable_Wrapper() {}

  inline iterator       begin()       { return iterator(wrapped_container.begin());}
  inline const_iterator begin() const { return const_iterator(wrapped_container.begin());}

  Container<T> wrapped_container;

};

int main()
{
  Container<int> c{5};
  auto it { c.begin() };
  std::cout << *it << std::endl;

  const Container<int> c2{10};
  auto it2 { c2.begin() };
  std::cout << *it2 << std::endl;


  Iterable_Wrapper<int> w{15};
  auto it3 { w.begin() };
  std::cout << *it3 << std::endl;

  return 0;
}

为了提供更多上下文,我正在尝试重新实现一些数据结构作为练习,我现在正在努力研究“复合”数据结构(HashSet,一个过于简化的版本的 unordered_set ) 实现为 vector带有 linked_list 的水桶在他们每个人中。 vector 和 list 实现都是我自己的,因此实现中的错误很可能是上坡路,这就是最小示例如此长的原因。我需要包括两个“模拟”类。

正如我所说,上面的代码无法编译,如果我运行 g++ file.cpp -std=c++11 给我

file.cpp:61:57: error: expected ‘;’ before ‘<’ token

即他在期待 using c_iterator = typename Container<T>::C_Iterator<Is_Const>;成为using c_iterator = typename Container<T>::C_Iterator相反。

很奇怪,如果我运行它确实会提示 error: ‘typename Container<int>::C_Iterator’ names ‘template<bool Is_Const> struct Container<int>::C_Iterator’, which is not a type

所以模板应该在那里!我的代码有什么问题?

编辑:我想到了尝试使用 clang++ 进行编译的好主意它建议我将第 61 行修改为

using c_iterator = typename Container<T>::template C_Iterator<Is_Const>;

现在可以了;但是我不知道额外的是什么 ::template正在做,所以问题是.. 为什么我必须那样做?什么是 ::template提示编译器允许代码现在编译?

最佳答案

应该是

using c_iterator = typename Container<T>::template C_Iterator<Is_Const>;

关于C++ 模板化类给出 `error: non-template X used as template`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58031449/

相关文章:

c++ - 是否可以为 std::array 定义隐式转换运算符?

c++ - 模板接受具有一种特化的 throw 和 nothrow

c++ - 如何重置for循环中的值?

c++ - 初始化类模板的static constexpr成员变量

c++ - 对模板类的引用不明确 (C++)

c++ - for循环不执行

c++ - 在具有大量内存的 super 计算机中如何实现指针?

c++ - std::shared_ptr 的 vector 丢失数据

c++ - LZF 可能会使用不同的算法进行压缩

c++ - 在类中实现移动语义的规范方法