0

Im trying to convert the following header file into a seperate header and .cpp file.

    template <class T>
class Rolodex {
  public:
    /**
     * Creates a new empty Rolodex
     */
    Rolodex()
    {
        sentinel_ = new Item;
        sentinel_->value_ = T();
        sentinel_->next_  = sentinel_;
        sentinel_->prev_  = sentinel_;
        current_ = sentinel_;
    }

    ~Rolodex()
    {
        while (current_ != sentinel_) {
            delete_current();
        }
        delete sentinel_;
    }

    /**
     * Returns true if the Rolodex is positioned at the beginning.
     */
    bool is_before_first()
    {
        return current_ == sentinel_;
    }

    /**
     * Returns true if the Rolodex is positioned at the end.
     */
    bool is_after_last()
    {
        return current_ == sentinel_;
    }

    /**
     * Rotates the Rolodex one step forwards.
     */
    void rotate_forward()
    {
        current_ = current_->next_;
    }

    /**
     * Rotates the Rolodex one step backwards.
     */
    void rotate_backward()
    {
        current_ = current_->prev_;
    }

    /**
     * Returns the value of the current card.
     */
    const T &current_value()
    {
        return current_->value_;
    }

    /**
     * Inserts a new item after the current position and
     * positions the Rolodex at the newly inserted item.
     */
    void insert_after_current(const T &value)
    {
        Item *coming = new Item;
        coming->value_ = value;
        coming->next_  = current_->next_;
        coming->prev_  = current_;

        current_->next_->prev_ = coming;
        current_->next_ = coming;

        current_ = coming;
    }

    /**
     * Inserts a new item before the current position and
     * positions the Rolodex at the newly inserted item.
     */
    void insert_before_current(const T &value)
    {
        Item *coming = new Item;
        coming->value_ = value;
        coming->prev_  = current_->prev_;
        coming->next_  = current_;

        current_->prev_->next_ = coming;
        current_->prev_ = coming;

        current_ = coming;
    }

    /**
     * Deletes current item and positions the Rolodex
     * at the _following_ item
     */
    void delete_current()
    {
        Item *going = current_;
        current_->prev_->next_ = current_->next_;
        current_->next_->prev_ = current_->prev_;

        if (going->next_ == sentinel_)
            current_ = going->prev_;
        else
            current_ = going->next_;

        delete going;
    }

  private:
    struct Item {
        T value_;
        Item *next_;
        Item *prev_;
    };

    Item *sentinel_;
    Item *current_;
};

#endif /* ROLODEX_H_ */

However when i split them apart, if i don't include

template <class T>

in the header file i get an error trying to declare

T value;

but if i do i get multiple errors in the .cpp file saying Rolodex is not a file class or enumeration. Is there a different type I can use to declare my value; and if so how do i go about modifying the code to fit this. Any help is greatly appreciated im super lost

EDIT: Thank you all for your help, my understanding of the C++ classes was lacking and after some research on the similar threads you provided I fixed my issue.

  • 2
    You cannot define templates in a `.cpp` file, all templates should be available during compilation, i.e. they have to be completely included by `#include "foo.h"`, and for that they have to be in a header file – Alexey S. Larionov Jun 11 '20 at 08:30
  • 1
    Does this answer your question? [Storing C++ template function definitions in a .CPP file](https://stackoverflow.com/questions/115703/storing-c-template-function-definitions-in-a-cpp-file) – Klaus Jun 11 '20 at 08:32
  • @AlexLarionov does this mean my code would require a complete rework. For example i have the following Rolodex::Rolodex() { { sentinel_ = new Item; sentinel_->value_ = T(); sentinel_->next_ = sentinel_; sentinel_->prev_ = sentinel_; current_ = sentinel_; }. How do i go about removing use of T(); – Nicholas Fischer Jun 11 '20 at 08:33
  • You don't remove it, you move every definition for functions of class `Rolodex` in the header. Once there, it should work – Alexey S. Larionov Jun 11 '20 at 08:42
  • @Klaus thank you it does somewhat, still confused about explicit template instantiation. I included template at the top of my .cpp file but how do i go about the rest. I apologise for my very basic knowledge of classes – Nicholas Fischer Jun 11 '20 at 08:52
  • 2
    Simply follow to the duplicate and read the linked articles. It makes not much sense to repeat all this stuff here again. The question, why and how template code can (not) be moved to cpp files is fully discussed and explained. So I hope the question will be closed as all answers are available. If you have a sepcific / detailed question to an aspect of all that, feel free to ask again! – Klaus Jun 11 '20 at 08:57
  • "i get an error" - **what** error? Quote in full any errors you vaguely allude to in your question. – underscore_d Jun 11 '20 at 09:08
  • @Klaus thank you for your help, i needed to more closely read the thread you linked and ive fixed my problem. Apologies for the vagueness – Nicholas Fischer Jun 11 '20 at 09:14
  • @AlexLarionov Sorry, but your first comment is incorrect. What if I define in `.cpp` but include the `.cpp` file into `.h` file? – arsdever Jun 11 '20 at 11:20
  • @arsdever it's easier for him to think about `cpp` and `h` how it's generally accepted. Of course you can name and include files however you want – Alexey S. Larionov Jun 11 '20 at 12:52
  • It's easier, but not better. – arsdever Jun 11 '20 at 12:55

2 Answers2

3

If you don't know how the templates work, I would suggest reading the topic first.

You can define the template class members in a separate .cpp file, but you will also have to instantiate a class for all of the types you will be using. You can do such declaring a simple dummy object in the .h or .cpp file.

// tmpl.h

template <typename T>
struct S {
  S();
  T _a_field;
}

// tmpl.cpp

template <typename T>
S<T>::S() {}

S<int> dummy;

However, this is not a suggested approach. I personally would suggest defining all in a single tmpl.h file or in another file and include it into tmpl.h

arsdever
  • 1,111
  • 1
  • 11
  • 32
-1

when using templates the complete implementation needs to be in the header. You cannot use .cpp files for the method definitions, but if you would still like to separate interface and implementation. You can use .hpp for the class definition, .inl file for the method definitions. At the end of the .hpp file, you have to include the .inl file containing that implementation. You can learn more here, why template codes cannot be moved to .cpp file https://youtu.be/6wdCqNlnMjo

Owl66
  • 147
  • 12