3

I am writing a program which implements a suffix trie in C++. I am trying to declare a recursive function with no parameters, but which needs to pass a pointer to itself.

I am defining it thus

public:
    string longestRepeat(Node*);

in the header file, and

string Trie::longestRepeat(Node* start = &nodes[0]){
    string deepest = "";
    for(unsigned int i = 0; i < start->getEdges(); i++){
        string child_deepest = longestRepeat(start->getChild(i));
        if(child_deepest.length() > deepest.length())
            deepest = child_deepest;
    }
    return deepest;
}

in the .cpp file, where node is a previously declared data structure.

However simply calling trie.longestRepeat() in the main function results in the error "no matching function call for Trie::longestRepeat(). Candidate expects 1 argument, 0 provided".

Luke Collins
  • 1,433
  • 3
  • 18
  • 36

2 Answers2

4

You need to put the default parameter in the declaration (in the header file), if you put it on the second declaration (the definition), it will only be used by call that see the second declaration:

struct Trie {
    std::string longestRepeat(Node*);
};

int main() {
    Trie{}.longestRepeat(); // Error
}

std::string Trie::longestRepeat(Node *p = &nodes[0]) { }

void g() {
    Trie{}.longestRepeat(); // Ok
}

But what you should probably do is create a public version of longestRepeat that calls a private/protected version with &nodes[0]:

struct Trie {
    std::string longestRepeat() { // No arguments
        longestRepeat_(&nodes[0]);
    }
private:
    std::string longestRepeat_(Node *); // Real implementation
};
Holt
  • 36,600
  • 7
  • 92
  • 139
2

For a member function, default argument could be declared on the out-of-class definition, but calling the member function with the using of default argument is only possible in the tranlation unit that could see the definition.

That means you could move the definiton of Trie::longestRepeat to the header file to fix the error.

Or make things simpler, declare the default argument on the declaration instead of definition. e.g.

// header
public:
    string longestRepeat(Node* start = &nodes[0]);

// implementation
string Trie::longestRepeat(Node* start) {
    ...
}

For a member function of a non-template class, the default arguments are allowed on the out-of-class definition, and are combined with the default arguments provided by the declaration inside the class body.

class C {
    void f(int i = 3);
    void g(int i, int j = 99);
};
void C::f(int i = 3) {         // error: default argument already
}                              // specified in class scope
void C::g(int i = 88, int j) { // OK: in this translation unit,
}                              // C::g can be called with no argument
songyuanyao
  • 169,198
  • 16
  • 310
  • 405