1

I want to define a binary tree class template like this:

template<typename Any>
class tree {
    public:
        struct treeNode {
            Any &_data;
            treeNode *_left, *_right;
            treeNode(const Any &data, treeNode *left = nullptr,
                     treeNode *right = nullptr) :
                     _data(data), _left(left), _right(right) {
            }
        };
    // ...
        std::vector<treeNode *> lookfor(
                const treeNode *, const std::function<bool(const Any &)> &) const;
};

// ↑ tree.h
// ↓ tree.cpp

template<typename Any>
std::vector<tree::treeNode *> tree<Any>::lookfor(
        const treeNode *x, const std::function<bool(const Any &)> &cmp) const {
    // ...
}

Then g++ was not happy and told me this:

tree.cpp:129:29: error: template argument 1 is invalid
 std::vector<tree::treeNode *> tree<Any>::lookfor(
                             ^
tree.cpp:129:29: error: template argument 2 is invalid
tree.cpp:129:31: error: prototype for ‘int tree<Any>::lookfor(const tree<Any>::treeNode*, const std::function<bool(const Any&)>&) const’ does not match any in class ‘tree<Any>’
 std::vector<tree::treeNode *> tree<Any>::lookfor(
                               ^
In file included from tree.cpp:1:0:
tree.h:88:33: error:                 std::vector<tree<Any>::treeNode*> tree<Any>::lookfor(const tree<Any>::treeNode*, const std::function<bool(const Any&)>&) const
         std::vector<treeNode *> lookfor(
                                 ^

So I wonder why it happened and how I can fix this bug.

I'm not good at English and this is my first time asking a question on statckoverflow so if I have made any mistake please tell me :)

Citron
  • 13
  • 3
  • 1
    Side note: `Any &_data` is initialized with `const Any &data` –  Dec 10 '14 at 18:18
  • 1
    [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Mooing Duck Dec 10 '14 at 18:26

1 Answers1

5

The code:

std::vector<tree::treeNode *> tree<Any>::lookfor

Is referencing tree, which is a template, without template arguments. It should be something like:

std::vector<typename tree<Any>::treeNode *> tree<Any>::lookfor

Also, as these are templates you shouldn't have a .cpp file for tree, that is also causing problems.

MatiasFG
  • 576
  • 2
  • 8
  • 2
    `std::vector::treeNode *> tree::lookfor` –  Dec 10 '14 at 18:15
  • 1
    Right! But please notice this is not required in C++11 anymore: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#409 Also, it isn't necessary in gcc 4.3.4 and forward: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=9634 – MatiasFG Dec 10 '14 at 18:21
  • g++ -std=c++11 (4.8.2) needs the typename –  Dec 10 '14 at 18:28
  • 2
    @MatiasFG, `typename` is still needed for dependent names, the links you quote don't change that. `tree` is clearly dependent, because `Any` is a template parameter. – Jonathan Wakely Dec 10 '14 at 18:30
  • Thank you. I moved the codes in .cpp to the header file and it worked XD – Citron Dec 11 '14 at 03:54