0

So I'm working through a C++ data structures class at my university and as part of the style guide, any class member functions longer than 10 lines of codes must be defined outside of the class.

Currently we are building a Binary Search Tree and I've come a across a situation where I need to define a function outside of the class because it is too long. Here is the general form of it with the relevant information:

Current Class Definition

template<typename T>
class BST {
private:
    struct Node {
        T data;
        Node* rightChild;
        Node* leftChild;
    }

    Node* searchNode(Node* node, const T& data) const {
        //Function definition, somewhat long
    }

public:
    //Other member functions
}

So I'd like to only declare this function in the class declaration and then define it elsewhere in a separate cpp file like this:

Proposed BST.h Portion

template<typename T>
class BST {
private:
    struct Node {
        T data;
        Node* rightChild;
        Node* leftChild;
    }

    Node* searchNode(Node*, const T&) const;

public:
    //Other member functions
}

Proposed BST.cpp Portion

#include "BST.h"

template<typename T>
Node* BST<T>::searchNode(Node* node, const T& data) const {
    //Function Declaration, somewhat long
}

However my compiler will no longer recognize the Node type because I am now outside of my class. Is there any way to get around this nicely? Or will I just have to live with it defined inside my class declaration?

Thanks for your time!

  • You should also read ["Why can templates only be implemented in the header file?"](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file). – G.M. Mar 24 '20 at 16:06

1 Answers1

1

It's possible. Because the return type comes before the name of the function---so the compiler doesn't yet know that you're defining a member of BST<T>---you have to specifically tell it that Node is a member of that class. You must use a qualified name:

template<typename T>
typename BST<T>::Node* BST<T>::searchNode(Node* node, const T& data) const {
    //Function Declaration, somewhat long
}

(In C++20, typename can be omitted.)

You can also use a trailing return type to avoid the extra qualification:

template<typename T>
auto BST<T>::searchNode(Node* node, const T& data) const -> Node* {
    //Function Declaration, somewhat long
}

Here, because the compiler has already seen that the function is a member of BST<T>, it will look up Node* in that class.

The fact that Node is private does not matter here. The private name Node is being "used" by the member function definition, which is part of the class, so access is allowed.

Brian Bi
  • 111,498
  • 10
  • 176
  • 312