-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Thank you for this interesting library!
I am trying to reproduce the example in the documentation, but with a templated type hierarchy.
Without templates
First, my version of the example without templates:
#include <iostream>
#include <memory>
#include <boost/openmethod.hpp>
#include <boost/openmethod/initialize.hpp>
#include <boost/openmethod/interop/std_shared_ptr.hpp>
using boost::openmethod::virtual_ptr;
using namespace boost::openmethod::aliases;
struct Node {};
struct Variable : Node {
int v;
Variable(int v) : v(v) {}
};
struct Plus : Node {
shared_virtual_ptr<Node> left, right;
Plus(shared_virtual_ptr<Node> left, shared_virtual_ptr<Node>right)
: left(left), right(right) {}
};
struct Times : Node {
shared_virtual_ptr<Node> left, right;
Times(shared_virtual_ptr<Node> left, shared_virtual_ptr<Node>right)
: left(left), right(right) {}
};
BOOST_OPENMETHOD(value, (virtual_ptr<const Node> node), int);
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<const Variable> var), int) {
return var->v;
}
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<const Plus> plus), int) {
return value(plus->left) + value(plus->right);
}
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<const Times> times), int) {
return value(times->left) * value(times->right);
}
BOOST_OPENMETHOD_CLASSES(Node, Variable, Plus, Times);
int main(int argc, char* argv[]) {
boost::openmethod::initialize();
shared_virtual_ptr<Node> a = make_shared_virtual<Variable>(2),
b = make_shared_virtual<Variable>(3),
c = make_shared_virtual<Variable>(4),
d = make_shared_virtual<Plus>(a, b),
e = make_shared_virtual<Times>(d, c);
std::cout << "a = " << value(a) << std::endl;
std::cout << "b = " << value(b) << std::endl;
std::cout << "c = " << value(c) << std::endl;
std::cout << "d = " << value(d) << std::endl;
std::cout << "e = " << value(e) << std::endl;
return 0;
}This outputs
a = 2
b = 3
c = 4
d = 5
e = 20
as expected.
With templates
#include <iostream>
#include <memory>
#include <boost/openmethod.hpp>
#include <boost/openmethod/initialize.hpp>
#include <boost/openmethod/interop/std_shared_ptr.hpp>
#include <boost/openmethod/macros.hpp>
using boost::openmethod::method;
using boost::openmethod::use_classes;
using boost::openmethod::virtual_ptr;
using namespace boost::openmethod::aliases;
template<typename T>
struct Node {};
template<typename T>
struct Variable : Node<T> {
T v;
Variable(T v) : v(v) {}
};
template<typename T>
struct Plus : Node<T> {
shared_virtual_ptr<Node<T>> left, right;
Plus(shared_virtual_ptr<Node<T>> left, shared_virtual_ptr<Node<T>>right)
: left(left), right(right) {}
};
template<typename T>
struct Times : Node<T> {
shared_virtual_ptr<Node<T>> left, right;
Times(shared_virtual_ptr<Node<T>> left, shared_virtual_ptr<Node<T>>right)
: left(left), right(right) {}
};
struct BOOST_OPENMETHOD_ID(value);
template<typename T>
using value = method<BOOST_OPENMETHOD_ID(value),
T(virtual_ptr<const Node<T>> node)>;
template<typename T>
T variable_value(virtual_ptr<const Variable<T>> var) {
return var->v;
}
template<typename T>
T plus_value(virtual_ptr<const Plus<T>> plus) {
return value(plus->left) + value(plus->right);
}
template<typename T>
T times_value(virtual_ptr<const Times<T>> times) {
return value(times->left) * value(times->right);
}
// Compile fails with "error: expected unqualified-id"
template<typename T>
static value<T>::override<variable_value<T>> override_variable_value;
template<typename T>
static value<T>::override<plus_value<T>> override_plus_value;
template<typename T>
static value<T>::override<times_value<T>> override_times_value;
#define NODE_IMPL(T, NAME) \
use_classes<Node<T>, Variable<T>, Plus<T>, Times<T>> NAME;
NODE_IMPL(float, float_node_classes);
int main(int argc, char* argv[]) {
boost::openmethod::initialize();
shared_virtual_ptr<Node<float>> a = make_shared_virtual<Variable<float>>(2),
b = make_shared_virtual<Variable<float>>(3),
c = make_shared_virtual<Variable<float>>(4),
d = make_shared_virtual<Plus<float>>(a, b),
e = make_shared_virtual<Times<float>>(d, c);
std::cout << "a = " << value<float>::fn(a) << std::endl;
std::cout << "b = " << value<float>::fn(b) << std::endl;
std::cout << "c = " << value<float>::fn(c) << std::endl;
std::cout << "d = " << value<float>::fn(d) << std::endl;
std::cout << "e = " << value<float>::fn(e) << std::endl;
return 0;
}This does not compile, as indicated by the comment in the code:
/usr/bin/c++ -DBOOST_CONTAINER_NO_LIB -DBOOST_JSON_NO_LIB -DFMT_SHARED -isystem /opt/homebrew/include -std=c++2b -arch arm64 -fcolor-diagnostics -Werror=return-type -Werror=switch -MD -MT CMakeFiles/templated.dir/templated.cpp.o -MF CMakeFiles/templated.dir/templated.cpp.o.d -o CMakeFiles/templated.dir/templated.cpp.o -c /Users/jagot/work/projects/examples/boost-openmethods/templated.cpp
/Users/jagot/work/projects/examples/boost-openmethods/templated.cpp:49:26: error: expected unqualified-id
49 | static value<T>::override<variable_value<T>> override_variable_value;
| ^
/Users/jagot/work/projects/examples/boost-openmethods/templated.cpp:57:26: error: expected unqualified-id
57 | static value<T>::override<plus_value<T>> override_plus_value;
| ^
/Users/jagot/work/projects/examples/boost-openmethods/templated.cpp:65:26: error: expected unqualified-id
65 | static value<T>::override<times_value<T>> override_times_value;
| ^
3 errors generated.
What I am doing wrong? Is it possible to accomplish the same less verbosely, i.e. using the macros, and such that value is a callable function, so I don't have to call using value<T>::fn?
Side note
My code is already written using lots of shared_ptrs. Is it possible to somehow call an open method using shared pointers directly, without the intermediate conversion to shared_virtual_ptr?
In the documentation found here, make_unique_virtual is written as make_unique_virtual_ptr, and similarly for make_shared_virtual. Luckily, my compiler told me to use the correct method.