0
    //Version 1
    template <typename T>
    class Node<T> {
        private:
            T data;
            Node *next;
        public:
            Node(T data) {
                this->data = data;
                this->next = NULL;
            }
    };


    //Version 2
    template <typename T>
    class Node {
        private:
            T data;
            Node *next;
        public:
            Node(T);
    };
    template <typename T>
    Node<T>::Node(T val) {
        data = val;
        next = NULL;
    }

I am confused on what the difference is between making a class using version 1 compared to making a class using version 2. What is the preferred way, Version 1 or Version 2?

user4860206
  • 41
  • 2
  • 6

3 Answers3

3

Firstly, the second one simply does not compile. A correct syntax is

template <typename T>
Node<T>::Node(T val) {  // note the <T> part

But apart from this, there is no difference from the point of view of a compiler.

However, there is difference from the point of view of a programmer. It is generally considered wrong to pollute class declaration with implementation. Another programmer who wants to use your code (or even you yourself when you move to another part of your project) should be able to understand what your code does without looking at implementation, therefore you should not pollute class declaration with implementation details.

Even better will be to separate code into a separate .cpp file, and #include that .cpp file into a header (the latter being a requirement for a templated class unless you use explicit instantiation). (Sometimes an extension other than .cpp, for example .tpp, is used for this purpose, but anyway the file should be included into the header.)


A separate note is that you should stick to member initialization lists in your constructors:

template <typename T>
Node::Node(T val): data(val), next(NULL) 
{}
Petr
  • 9,812
  • 1
  • 28
  • 52
  • "...separate code into a separate .cpp file", considering this is a template, the OP is already putting the implementation [in the right place](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file?s=2|2.6765), so I'm not sure why this is even mentioned as part of this answer. – WhozCraig May 05 '15 at 19:33
  • @WhozCraig, note the "...and #include in into a header" in my answer, and "A common solution to this is to write the template declaration in a header file, then implement the class in an implementation file (for example .tpp), and include this implementation file at the end of the header" in the link you gave. – Petr May 05 '15 at 19:34
  • @WhozCraig, fixed explicit instantiation, my bad. Also rephrased that part to make it more clear that the implementation should be still `#include`d into the header. – Petr May 05 '15 at 19:37
  • So you think version 2 is ideal? But instead of my version 2, I should add the implementations into a separate .cpp file? – user4860206 May 05 '15 at 19:49
  • I don't like the word 'ideal' as it's too strong, but personally I would choose version 2 with implementation in a separate file `#include`'d into the header (and with initializer lists). See also the question linked by WhozCraig – Petr May 05 '15 at 20:18
0

I would go with version 1 but without the explicit this pointers and member initializers:

//Version 1'
template <typename T>
class Node {
    private:
        T data;
        Node *next;
    public:
        Node(T _data) : data(_data), next(0) { }
};

For version 2 the namespace access with "::" is normally used in implementation files (.cc .cpp ...) and not in headers afaik

  • true, for version 1 the constructor is enclosed with in the class struct, well it was sloppy to call the class/struct name a namespace in case of version 2. –  May 05 '15 at 19:26
0

Formally, in the first version the constructor is inline, in the second version it is not. However for templates and modern optimizing compilers, this difference is immaterial: Since it is a template, the definition has to be in the same file anyway, and the optimizer likely ignores the optimization hint since it can determine by itself when the function is worthy of being inlined (which for such a simple function is always).

celtschk
  • 19,311
  • 3
  • 39
  • 64