模板类“序列/类名称未命名类型”错误

时间:2017-10-08 19:38:31

标签: c++ templates

我目前正在尝试用C ++学习模板,但我无法理解当前的错误。

我试图根据书中的代码示例编写一个序列类。我一直反复得到这个错误。

我需要以模块方式编写此模板。功能工作,但我找不到错误的来源。我试过更改.cpp文件的名称没有成功。

这段代码几乎与我在书中发现并运行的代码完全相同。

这是标题和实现文件的代码。

#ifndef SEQUENCE_H
#define SEQUENCE_H

#include <cstdlib>  // provides size_t

namespace CS3358_FA17_A04_sequenceOfNum
{
   template <class Item>
   class sequence
   {
   public:
      // TYPEDEFS and MEMBER CONSTANTS
      typedef Item value_type;
      typedef size_t size_type;
      static const size_type CAPACITY = 10;
      // CONSTRUCTOR
      sequence();
      // MODIFICATION MEMBER FUNCTIONS
      void start();
      void end();
      void advance();
      void move_back();
      void add(const Item& entry);
      void remove_current();
      // CONSTANT MEMBER FUNCTIONS
      size_type size() const;
      bool is_item() const;
      Item current() const;

   private:
      Item data[CAPACITY];
      size_type used;
      size_type current_index;
   };
}

#include "sequence.hpp"

.HPP文件:

namespace CS3358_FA17_A04_sequenceOfNum
{
   template <class Item>
   sequence<Item>::sequence() : used(0), current_index(0) { }

   template <class Item>
   void sequence<Item>::start() { current_index = 0; }

   template <class Item>
   void sequence<Item>::end()
   {
      current_index = (used > 0) ? used - 1 : 0;
   }

   template <class Item>
   void sequence<Item>::advance()
   {
      assert( is_item() );
      ++current_index;
   }

   template <class Item>
   void sequence<Item>::move_back()
   {
      assert( is_item() );
      if (current_index == 0)
         current_index = used;
      else
         --current_index;
   }

   template <class Item>
   void sequence<Item>::add(const Item& entry)
   {
       assert( size() < CAPACITY );

      size_type i;

      if ( ! is_item() )
      {
         if (used > 0)
            for (i = used; i >= 1; --i)
               data[i] = data[i - 1];
         data[0] = entry;
         current_index = 0;
      }
      else
      {
         ++current_index;
         for (i = used; i > current_index; --i)
            data[i] = data[i - 1];
         data[current_index] = entry;
      }
      ++used;
   }

   template <class Item>
   void sequence<Item>::remove_current()
   {
      assert( is_item() );

      size_type i;

      for (i = current_index + 1; i < used; ++i)
         data[i - 1] = data[i];
      --used;
   }

   template <class Item>
   typename sequence<Item>::size_type sequence<Item>::size() const { return used;}

   template <class Item>
   bool sequence<Item>::is_item() const { return (current_index < used); }

   template <class Item>
   typename sequence<Item>::Item sequence<Item>::current() const
   {
      assert( is_item() );

      return data[current_index];
   }
}

错误是:

序列没有命名类型 - &gt;这发生在每个函数

'&lt;'之前的预期初始化程序每个地方都使用模板说明符。

之前我编写过很多模板,但由于编译器和链接器问题,我总是在同一个文件中定义和实现。

非常感谢任何帮助,这里有一个完整的错误列表及其行。

g++ -Wall -ansi -pedantic -c sequence.cpp
sequence.cpp:48:4: error: ‘sequence’ does not name a type
    sequence<Item>::sequence() : used(0), current_index(0) { }
    ^
sequence.cpp:51:17: error: expected initializer before ‘<’ token
    void sequence<Item>::start() { current_index = 0; }
                 ^
sequence.cpp:54:17: error: expected initializer before ‘<’ token
    void sequence<Item>::end()
                 ^
sequence.cpp:60:17: error: expected initializer before ‘<’ token
    void sequence<Item>::advance()
                 ^
sequence.cpp:67:17: error: expected initializer before ‘<’ token
    void sequence<Item>::move_back()
                 ^
 sequence.cpp:77:17: error: expected initializer before ‘<’ token
    void sequence<Item>::add(const Item& entry)
                 ^
sequence.cpp:102:17: error: expected initializer before ‘<’ token
    void sequence<Item>::remove_current()
                 ^
sequence.cpp:114:4: error: ‘sequence’ does not name a type
    sequence<Item>::size_type sequence<Item>::size() const { return used;         }
    ^
sequence.cpp:117:17: error: expected initializer before ‘<’ token
    bool sequence<Item>::is_item() const { return (current_index < used);     }
                 ^
sequence.cpp:120:4: error: ‘sequence’ does not name a type
    sequence<Item>::Item sequence<Item>::current() const

这是Makefile,还编辑了我在文件扩展名中的更改。

a4s1: sequence.o sequenceTest.o
    g++ sequence.o sequenceTest.o -o a4s1

sequence.o: sequence.hpp sequence.h
    g++ -Wall -ansi -pedantic -c sequence.hpp

sequenceTest.o: sequenceTest.cpp sequence.hpp sequence.h
    g++ -Wall -ansi -pedantic -c sequenceTest.cpp

test:
    ./a4s1 auto < a4test.in > a4test.out

clean:
    @rm -rf sequence.o sequenceTest.o

cleanall:
    @rm -rf sequence.o sequenceTest.o a4s1

2 个答案:

答案 0 :(得分:1)

&#34; 在头文件中包含实现&#34;并不意味着#include <sequence.cpp>,这意味着实际拥有sequence.h中的所有内容。

可能的解决方案是:

  1. 将所有内容从sequence.cpp移动到sequence.h并删除sequence.cpp。
  2. 将sequence.cpp重命名为sequence.imp或其他扩展名,永远不会自行编译(将其从makefile中删除)。它将在#include sequence.h的.cpp文件中编译(这可能是你所要求的)。
  3. 保持sequence.cpp但#include <sequence.h>位于顶部并使用explicit template instantiation

答案 1 :(得分:0)

必须在他们使用的每个编译单元中定义模板,请参阅here。这通常意味着它们的实现必须放在头文件中。如果你想将实现放在一个单独的文件中,你可以创建一个“实现文件”并将它包含在标题的末尾。这似乎是你教授推荐的策略。

但是,您的构建系统可能不会将实现文件视为单独的编译单元。它应该以.imp或.hpp或其他内容结尾但不是.cpp。