0

I wanted to implement a simple binary tree in which the vertices hold lambdas.

class Element {
public:
    Element() { }
    virtual int operator()();
};

class Node : public Element {
private:
    std::function<int(Element, Element)> fn;
    Element left;
    Element right;
public:
    Node(std::function<int(Element, Element)> _fn, Element _left, Element _right)
        : fn(_fn), left(_left), right(_right) { }
    int operator()() { return fn(left, right); }
};

class Leaf : public Element {
private:
    int value;
public:
    Leaf(int _value) : value(_value) { }
    int operator()() { return value; }
};

int main() {
cout << Node([](Element a, Element b) { return a() + b(); }, Leaf(2), Leaf(5))() << endl;
return 0;
}

And here are errors which I'm getting:

g++ -Wall -std=c++11 -Wextra -pedantic tree.cc -c
g++ -Wall -std=c++11 -Wextra -pedantic tree.o -o tree
tree.o: In function `main::{lambda(Element, Element)#1}::operator()(Element, Element) const':
tree.cc:(.text+0x18): undefined reference to `vtable for Element'
tree.cc:(.text+0x2a): undefined reference to `vtable for Element'
tree.o: In function `Element::Element()':
tree.cc:(.text._ZN7ElementC2Ev[_ZN7ElementC5Ev]+0xf): undefined reference to `vtable for Element'
tree.o: In function `Element::Element(Element const&)':
tree.cc:(.text._ZN7ElementC2ERKS_[_ZN7ElementC5ERKS_]+0x13): undefined reference to `vtable for Element'
tree.o: In function `Node::Node(std::function<int (Element, Element)>, Element, Element)':
tree.cc:(.text._ZN4NodeC2ESt8functionIFi7ElementS1_EES1_S1_[_ZN4NodeC5ESt8functionIFi7ElementS1_EES1_S1_]+0x4e): undefined reference to `vtable for Element'
tree.o:tree.cc:(.text._ZN4NodeC2ESt8functionIFi7ElementS1_EES1_S1_[_ZN4NodeC5ESt8functionIFi7ElementS1_EES1_S1_]+0x5a): more undefined references to `vtable for Element' follow
tree.o:(.rodata._ZTI4Leaf[_ZTI4Leaf]+0x10): undefined reference to `typeinfo for Element'
tree.o:(.rodata._ZTI4Node[_ZTI4Node]+0x10): undefined reference to `typeinfo for Element'
collect2: error: ld returned 1 exit status
make: *** [tree] Error 1

What does it mean, is there a problem with classes declarations or I do not understand some aspects of functional programming in C++?

Stephen Dedalus
  • 227
  • 1
  • 2
  • 9

2 Answers2

1

You try to use polymorphism but without pointers/references. This does not work: Why doesn't polymorphism work without pointers/references?

Effectively

Element left;
Element right;

are always of type Element (not a derived type) and you try to call operator() on them. But this method was not implemented for Element, which is what the error messages are telling you.

Community
  • 1
  • 1
1

You are getting a link error because your base class Element is missing an implementation of the function call virtual int operator()(); operator overloaded function.

Other Issues with your design

  1. All references to base class should be const reference 's/Element/const Element&/'
  2. Element should be an ABC. The function call overload should be pure virtual.
  3. The Function Call overload should be of type const.

Modified Program

#include <iostream>
#include <functional>
using namespace std;
class Element {
public:
    Element() { }
    virtual int operator()() const = 0;
};

class Node : public Element {
private:
    std::function<int(const Element&,const Element&)> fn;
    const Element& left;
    const Element& right;
public:
    Node(std::function<int(const Element&, const Element&)> _fn, const Element& _left, const Element& _right)
        : fn(_fn), left(_left), right(_right) { }
    int operator()() const { return fn(left, right); }
};

class Leaf : public Element {
private:
    int value;
public:
    Leaf(int _value) : value(_value) { }
    int operator()() const { return value; }
};

int main() {
    cout << Node([](const Element& a,const Element& b) { return a() + b(); }, Leaf(2), Leaf(5))() << endl;
    return 0;
}
Abhijit
  • 62,056
  • 18
  • 131
  • 204
  • `Leaf(2)`'s and `Leaf(5)`'s lifetime ends when the constructor for `Node` returns. In the following call to `operator()` the references `left` and `right` are dangling. Or do I miss something? –  Jan 26 '14 at 15:56