I am trying to include a function pointer as a parameter in a class constructor to allow for any arbitrary function pointer to be stored as a member variable in the class. In the code examples this is shown as function
being assigned to FUNCTION
which is passed into the constructor and is of type typed_value (*)(typed_value, typed_value)
. Here typed_value
is a kind of std::variant
. I would like this to be any kind of function pointer for example,
type_value (*)(typed_value)
type_value (*)(typed_value, typed_value)
type_value (*)(typed_value, typed_value, typed_value)
and so on.
The class below inherits from NodeExtended
. I do not feel the function of that class is particularly pertainant but I'm happy to add it on request.
#pragma once
#include "NodeExtended.h"
#include <iostream>
class NonterminalNode: public NodeExtended<NonterminalNode>
{
public:
// Constructor
NonterminalNode(std::string, std::vector<std::string>, std::string, typed_value (*)(typed_value, typed_value));
// Destructor
~NonterminalNode();
// Connectors
void attach(std::vector<Node *>) override;
// Function type
typed_value (*function)(typed_value, typed_value);
// Evaluation
typed_value evaluate(reference_map_type & reference_map) override;
};
The implementation follows and the class is fairly vanilla except that extern "C"
functions are required to import the constructor into a factory class that loads them using dlsym
as this class is compiled as a shared library.
#include "NonterminalNode.h"
NonterminalNode::NonterminalNode(std::string NAME, std::vector<std::string> INPUT, std::string OUTPUT, typed_value (*FUNCTION)(typed_value, typed_value)) : NodeExtended(NAME, INPUT, OUTPUT) {
function = FUNCTION;
}
NonterminalNode::~NonterminalNode() = default;
void NonterminalNode::attach(std::vector<Node *> CHILDREN) {
children = CHILDREN;
}
typed_value NonterminalNode::evaluate(reference_map_type & reference_map) {
return function(children[0]->evaluate(reference_map), children[1]->evaluate(reference_map));
}
extern "C" Node * create_object(std::string NAME, std::vector<std::string> INPUT, std::string OUTPUT, typed_value (*FUNCTION)(typed_value, typed_value))
{
return new NonterminalNode(NAME, INPUT, OUTPUT, FUNCTION);
}
extern "C" void destroy_object(Node * object)
{
delete object;
}
My first instinct was to template the class but I'm getting all sorts of errors thrown at me. Could somebody walk me through how to do this for this example or perhaps suggest an alternative. For example something like
#pragma once
#include "NodeExtended.h"
#include <iostream>
template <class arity>
class NonterminalNode: public NodeExtended<NonterminalNode<arity>>
{
public:
// Constructor
NonterminalNode(std::string, std::vector<std::string>, std::string, arity);
// Destructor
~NonterminalNode();
// Connectors
void attach(std::vector<Node *>) override;
// Function type
arity function;
// Evaluation
typed_value evaluate(reference_map_type & reference_map) override;
};
template <class arity>
inline
NonterminalNode<arity>::NonterminalNode(std::string NAME, std::vector<std::string> INPUT, std::string OUTPUT, arity FUNCTION) : NodeExtended(NAME, INPUT, OUTPUT) {
function = FUNCTION;
}
Edit 1:
With the above changes I receive the error
error: class ‘NonterminalNode<arity>’ does not have any field named ‘NodeExtended’
Occurring at:
NonterminalNode<arity>::NonterminalNode(std::string NAME, std::vector<std::string> INPUT, std::string OUTPUT, typed_value (*FUNCTION)(typed_value, typed_value)) : NodeExtended(NAME, INPUT, OUTPUT) {
Similarly seen here however, I don't believe the solution applies.