0

I'm currently trying to learn templates in C++ and am unable to make sense of this current Error.

I was trying to write a sequence class based out of a code example from the book. I keep getting this error repeatedly.

I am required to write this template modularly. The functions work, but i can't find the source of the errors. I have tried changing name of .cpp file with no success.

This code is nearly identical to that which i found and ran in the book which compiled with no issues.

Here is my Code for header and implementation files.

#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 File:

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];
   }
}

Error's Are:

sequence does not name a type -> this occurs in every function

expected initializer before '<' every place a template specifier is used.

I have written many templates before, but i have always defined and implemented in the same file because of compiler and linker issues.

Any help would be much appreciated, here is a complete list of errors and their lines.

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

Here is Makefile, Also edited my changes in the file extensions.

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
Sap163
  • 25
  • 3
  • 3
    Did you include the header? Also, https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – Rakete1111 Oct 08 '17 at 19:41
  • 1
    Templates can only be imlemented in header files, see [here](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – Knoep Oct 08 '17 at 19:48
  • @knoep, you mean templates that you want to use in more than one file should be declared in a header file. – Surt Oct 08 '17 at 20:00
  • I'm doing this as a school assignment and the book states there are 2 different ways to implement. I have implemented all my previous templates in a single header file, but this is not the task i am trying to accomplish. I simply can't track the error. I assume its somewhere in the linker or how it is being compiled. @Rakete1111 I was instructed by the book to include the implementation in the header file. There is no main function. I'm just trying to compile the template before i can test. – Sap163 Oct 08 '17 at 20:03
  • You forgot to `#include` your header file into your .cpp file. – n. m. could be an AI Oct 08 '17 at 20:04
  • @Surt Yeah, of course, but it is generally the point of header files to be included in more than one file and it seems to cause the OP's problems. I just wanted to quickly explain where the problem is and send him off to an detailed discussion. – Knoep Oct 08 '17 at 20:05
  • @n.m. My appologies, i'm new to posting. My code has been updated. This was included before i compiled. – Sap163 Oct 08 '17 at 20:07
  • Try renaming your .cpp file to something like .imp. Otherwise it will be treated as a seperat compilation unit which it is not in your case. – Knoep Oct 08 '17 at 20:09
  • You have included your .cpp file in the header ... usually you do it the other way around. – Surt Oct 08 '17 at 20:09
  • see the comment of @Knoep. You can do one thing. Instead of cpp extension make it hpp and include hpp file as header file in your cpp file. Else best option is put all codes inside the header file only. – Abhijit Pritam Dutta Oct 08 '17 at 20:10
  • My professor insisted i do it this way and that it was good practice. If i had my choice i'd put it all into a header file and be done with it. I've never written a template this way before. I have renamed my implementation file to .hpp file extension and modified makefile accordingly. I am still getting the same errors. – Sap163 Oct 08 '17 at 20:17
  • That is interesting… Can you post the makefile? – Knoep Oct 08 '17 at 20:25
  • 1
    remove `sequence.o: sequence.hpp sequence.h g++ -Wall -ansi -pedantic -c sequence.hpp` from your makefile. Its not a compilation unit, its just a header. – Knoep Oct 08 '17 at 20:32

2 Answers2

1

"include the implementation in the header file" doesn't mean #include <sequence.cpp>, it means to actually have everything in sequence.h.

The possible solutions are:

  1. Move everything from sequence.cpp to sequence.h and delete sequence.cpp.
  2. Rename sequence.cpp to sequence.imp or some other extension and never compile it by itself (remove it from the makefile altogether). It will be compiled in the .cpp file(s) that #include sequence.h (this is probably what is asked of you).
  3. Keep sequence.cpp but #include <sequence.h> at the top and use explicit template instantiation.
rustyx
  • 80,671
  • 25
  • 200
  • 267
0

Templates have to be defined in every compilation unit they're used in, see here. This usually means, that their implementation has to be put inside a header file. If you want to put the implementation in a separat file anyway, you can create an "implementation file" and include it at the end of your header. That seems to be the strategy your professor is recommending.

However, the implementation file may not be treated as separate compilation unit by your built system. It should end in .imp or .hpp or something else but not .cpp.

Knoep
  • 858
  • 6
  • 13