-
|
Thank you for this interesting library! I am trying to reproduce the example in the documentation, but with a templated type hierarchy. Without templatesFirst, 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 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: What I am doing wrong? Is it possible to accomplish the same less verbosely, i.e. using the macros, and such that Side noteMy code is already written using lots of In the documentation found here, |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Thanks! And sorry for the belated reply, I missed the issue. Gotta set some
There are a couple of issues here, but nothing major. template<typename T>
using value = method<BOOST_OPENMETHOD_ID(value),
T(virtual_ptr<const Node<T>> node)>;
template<typename T>
T plus_value(virtual_ptr<const Plus<T>> plus) {
return value(plus->left) + value(plus->right);
}
template<typename T>
T plus_value(virtual_ptr<const Plus<T>> plus) {
return value<T>::fn(plus->left) + value<T>::fn(plus->right);
}Secondly, this is wrong in several ways: template<typename T>
static value<T>::override<variable_value<T>> override_variable_value;
template<typename T>
typename value<T>::template override<variable_value<T>> override_variable_value;Note that, at this point, no In this situation, I would go this way: template<class T>
using node_impl = std::tuple<
use_classes<Node<T>, Variable<T>, Plus<T>, Times<T>>,
typename value<T>::template override<
variable_value<T>,
plus_value<T>,
times_value<T>
>
>;
node_impl<float> node_impl_float;Godbolt: https://godbolt.org/z/7rs4dor59
Macros and templates don't play ball, in part because macros don't see angle brackets as brackets at all. Also, the syntax of templates is very verbose, and evolves with every revision of the standard. For example, the macro would need to handle
You could. There is an implicit conversion from a reference to an object to a template<typename T>
struct Node {virtual ~Node() = default;};
// ...
int main(int argc, char* argv[]) {
boost::openmethod::initialize();
std::shared_ptr<Node<float>> a = std::make_shared<Variable<float>>(2);
std::cout << "a = " << value<float>::fn(*a) << std::endl;
return 0;
}See,
Corrected in 1.91 ;-) |
Beta Was this translation helpful? Give feedback.
Thanks! And sorry for the belated reply, I missed the issue. Gotta set some
email rules...
There are a couple of issues here, but nothing major.
valueis a class template and you are calling it as a function. The correct syntax is:Secondly, this …