Stan
Stan

Reputation: 89

How to pass functions as parameters within a class?

I am trying to pass my print function as a paramater through my inordertraversal class which belongs to a templated binarySearchTree. whenever I define these functions within main the program works fine but whenever i try to encapsulate them I get a error:

"expected primary-expression before '&' token"

This is the code that works

void print(classdatatype& x); 
int main()
{
    binarySearchTree<classdatatype> tree;
    tree.inorderTraversal(print);
    return 0;
}

void print(classdatatype& x)   {  cout << x << " ";      } 

The declaration of my inordertraveral templated class is

template <class elemType>
void binarySearchTree<elemType>::inorderTraversal(void (*visit)(elemType& item))

I can show the rest of the code if needed but this all works just fine

Once I move these functions into my class it looks like this (the declarations for print and the binarySearchTree are in the .cpp same as they are declared above)

void bst::printfunctions(classdatatype& x)
{
    tree.inorderTraversal(print(classdatatype & x)); //error here
}

void bst::print(classdatatype& x) 
{ 
    cout << x << " "; 
} 

The error is to do within the brackets of print, I have tried many different things but to me this is the correct declaration; therefore I don't know why it's not working.

Any advice would be greatly appreciated.


EDIT: print is a function pointer to print the details of classdatatype which is stored inside a binary search tree.


EDIT2: minimal reproducible example.

Data types are as they are and not like in the above example. This is as basic as I could make this and I ended up getting another error which I couldn't resolve but for the purpose of this example it doesn't matter and should be ignored. main() is included but is minimal and may not serve its purpose but the problem doesn't lie here anyway.

main()

#include <iostream>
#include "windlogtype.h"
using namespace std;

int main()
{
    windlogtype wind;

    ifstream infile("data.txt");
    //for purose of this data is one integer value
    infile >> wind;

    //do something
    //main purpose is to get input
    return 0;
}

class windlogtype

#include "windlogtype.h"
windlogtype::windlogtype() { }    
windlogtype::windlogtype(int i)     {   num = i; }    
int windlogtype::Getnumber() const  {   return num; }    
void windlogtype::Setnumber(int i)  {   num = i; }    
ostream operator<<(ostream& os, const windlogtype& w)
{
    os << w.Getnumber() << '\n';
    return os;
}

#ifndef WINDLOGTYPE_H
#define WINDLOGTYPE_H

#include <iostream>
using namespace std;

class windlogtype
{
public:
    windlogtype();
    windlogtype(int i);
    int Getnumber() const;
    void Setnumber(int i);
private:
    int num;
};
ostream operator<<(ostream& os, const windlogtype& w);

#endif // WINDLOGTYPE_H

class binarySearchTree

#include <iostream>
#include <assert.h>
using namespace std;

template <class elemType> struct binaryTreeNode
{
    elemType info;
    binaryTreeNode<elemType>* llink;
    binaryTreeNode<elemType>* rlink;
};

template <class elemType> class binarySearchTree
{
public:
    const binarySearchTree<elemType>& operator=(const binarySearchTree<elemType>&);
    void inorderTraversal(void (*visit) (elemType&));
    binarySearchTree();
    ~binarySearchTree();
    binaryTreeNode<elemType>* root;
private:
    void inorder(binaryTreeNode<elemType>* p, void (*visit) (elemType&));
};

template <class elemType> binarySearchTree<elemType>::binarySearchTree() {
    root = NULL;
}    
template <class elemType> void binarySearchTree<elemType>::inorderTraversal(void (*visit) (elemType& item))
{
    inorder(root, *visit);
}    
template <class elemType> void binarySearchTree<elemType>::inorder(binaryTreeNode<elemType>* p, void (*visit) (elemType& item))
{
    if (p != NULL)
    {
        inorder(p->llink, *visit);
        (*visit)(p->info);
        inorder(p->rlink, *visit);
    }
}

class bst

#ifndef BST_H
#define BST_H
#include "binarySearchTree.h"
#include "windlogtype.h"
using namespace std;

class bst
{
public:
    bst();
    void InsertTree(windlogtype& newwind);
    void printfunctions(windlogtype& x);
    binarySearchTree<windlogtype>& GetTree();
    void print(windlogtype& x);
private:
    binarySearchTree<windlogtype> treeRoot;
};    
#endif // BST_H

#include "bst.h"

bst::bst(){/*ctor*/ }    
binarySearchTree<windlogtype>& bst::GetTree() {     return treeRoot;  }
void bst::print(windlogtype& x)               {     cout << x << " ";  }
void bst::printfunctions(windlogtype& x)
{
    treeRoot.inorderTraversal(print(windlogtype & x)); // error lies here
}

Upvotes: 2

Views: 141

Answers (1)

JeJo
JeJo

Reputation: 32722

The

void bst::print(classdatatype& x) // is a member function

and

void print(classdatatype& x);    // is a free function.

Hence the function pointers to hold them will be also different.


The OP has mentioned in the comments, that he/she wants to pass the member function print() from bst class to member functioninorderTraversal() of binarySearchTree<elemType> class. In that case passing the member-function is not sufficient, in addition to that the instance of the class to which the print function will be called also should be passed.

The Lambda function can come in handy to simplify this by capturing the instance of bst class and pass to the inorderTraversal() of the binarySearchTree class.

That means, inside template <class elemType> class binarySearchTree provide:

template<typename Callable>
void inorderTraversal(Callable visit)
{
    inorder(root, visit);  // simply pass visit further
    // or avoid coping by warapping std::cref(): i.e. inorder(root, std::cref(visit));
}

template<typename Callable>
void inorder(binaryTreeNode<elemType>* p, Callable visit)
{
    if (p != NULL)
    {
        inorder(p->llink, visit);  // or inorder(root, std::cref(visit));
        visit(p->info);            // call directly with parameter
        inorder(p->rlink, visit);  // or inorder(root, std::cref(visit));
    }
}

Inside the bst class

void printfunctions(windlogtype& x)
{
    // lambda captures the instance by copy
    const auto printThisLogType = [this](windlogtype & x)->void { this->print(x); };
    treeRoot.inorderTraversal(printThisLogType); // pass the callable lambda
}

Here is compiling code: https://godbolt.org/z/jhCnPs


PS: The other error was from operator<< of windlogtype class where you missed to return the reference of std::ostream.

To be honest, you could have made a further simpler minimal code, by replacing windlogtype with int and showing the defenitions of the member function next to the declaration. That would make the code to read easily.

Upvotes: 4

Related Questions