0

i was writing a BST class in C++ and wanted to add a default parameter to a function but, when i tried to the visual studio compiler gave compile and linking errors, so after a bit of googling, i made the root variable static inline and it worked, i want to know what does static inline change in this specific situation.

here's the BST class code:

#pragma once

template<typename T>
class BST
{
   template<typename T>
   struct node
   {
    T data;
    node<T>* left;
    node<T>* right;

    node(T d)
    {
        data = d;
        left = right = nullptr;
    }
  };


public:

BST()
{
    root = nullptr;
}

~BST()
{
    delete root;
}

node<T>* insert(T d)
{
    if (root == nullptr)
    {
        root = new node<T>(d);

        return root;
    }
    
    node<T>* current = root;
    node<T>* k = nullptr;
    

    while (current != nullptr)
    {
        k = current;

        if (current->data > d)
        {
            current = current->left;
        }
        else if (current->data < d)
        {
            current = current->right;
        }
    }

    if (k->data > d)
    {
        k->left = new node<T>(d);
    }
    else if (k->data < d)
    {
        k->right = new node<T>(d);
    }

    
    return root;
}


bool find(T d)
{
    if (root == nullptr)
    {
        std::cerr << "Tree is empty! : ";

        return false;
    }

    node<T>* current = root;
    node<T>* k = nullptr;

    while (current->data != d)
    {
        k = current;

        if (current->left == nullptr || current->right == nullptr && current->data != d)
        {
            std::cout << "Not Found! : ";
            
            return false;
        }

        if (current->data > d)
        {
            current = current->left;
        }
        else if (current->data < d)
        {
            current = current->right;
        }
    }

    return true;
}

node<T>* findmax()
{
    node<T>* temp = root;
    while (temp->right != nullptr)
    {
        temp = temp->right;
    }

    return temp;
}

node<T>* findmin(node<T>* temp = root)
{
    
    while (temp->left != nullptr)
    {
        temp = temp->left;
    }

    return temp;
}

private:
static inline node<T>* root;

};
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Programvarg
  • 31
  • 1
  • 6
  • im sorry if i worded it wrong, if i remove the static inline from the root variable then the code doesnt compile and if root is only static it throws linking errors so im interested what do those keywords change because it works with them – Programvarg Jan 18 '22 at 14:19
  • You may not use non-static class variables as default arguments. – Vlad from Moscow Jan 18 '22 at 14:20
  • 1
    You shouldn't add keywords to variables/functions for fun. First, go read about `static` and what it does inside a class then use it if it suits your need. `static root` will only be a standalone class member. Class instances won't have a separate instance of `root` anymore. And I think that's a wrong behavior in a BST class. – digito_evo Jan 18 '22 at 14:20
  • please post a [mcve] including the full compiler error message. The code you did post does not compile also with the `static inline`: https://godbolt.org/z/36r44xrrM – 463035818_is_not_an_ai Jan 18 '22 at 14:20
  • 2
    @463035818_is_not_a_number it does compile with msvc: https://godbolt.org/z/zv6PsEfsn – Alan Birtles Jan 18 '22 at 14:25

2 Answers2

2

According to the C++ 20 Standard (9.3.4.7 Default arguments)

  1. ...A non-static member shall not appear in a default argument unless it appears as the id-expression of a class member access expression (7.6.1.5) or unless it is used to form a pointer to member

So when the data member root was not declared as static then this function declaration with a default argument

node<T>* findmin(node<T>* temp = root)

was incorrect.

You could for example declare the function like

node<T>* findmin(node<T>* temp = nullptr )

In this case within the function you could check whether the parameter temp is a null pointer and if so you could assign it with the pointer root.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

This is because

The keyword this shall not be used in a default argument of a member function

and non static member of a class is bound to this (i.e. root is equivalent to this->root). More about default parameters restrictions here.

In your case you could have the following workaround:

node<T>* findmin(node<T>* temp = nullptr)
{
    if (temp == nullptr) temp = root;

however I am not sure if you should use it, for the sake of clarity.

pptaszni
  • 5,591
  • 5
  • 27
  • 43