c++ - Calling parametrised method on list items with different template parameters -
i'm trying store , manipulate list of template class objects different parameter types; template class has 2 parametrised methods, 1 returning parameter type , void 1 accepting input.
more specifically, have template class defined follows:
template<typename t> class test { public: virtual t a() = 0; virtual void b(t t) = 0; };
and different specifications of it, such as:
class testint : public test<int> { public: int a() { return 1; } void b(int t) { std::cout << t << std::endl; } }; class teststring : public test<std::string> { public: std::string a() { return "test"; } void b(std::string t) { std::cout << t << std::endl; } };
i'd able store in 1 single list different objects of both testint
, teststring
type , loop through calling 1 method input other, in:
for (auto = list.begin(); != list.end(); ++it) (*it)->b((*it)->a());
i've looked boost::any
i'm unable cast iterator specific class, because don't know specific parameter type of each stored object. maybe cannot done in statically typed language c++, wondering whether there way around it.
just sake of completeness, i'll add overall aim develop "parametrised observer", namely being able define observer (as observer pattern) different parameters: test
class observer class, while list of different types of observers i'm trying define stored within subject class, notifies them through 2 methods a()
, b()
.
the virtuals have no meaning here, since each t
signatures distinct.
so seems have yet version of eternal "how can emulate virtual functions templates" or "how create interface without virtual functions":
the first 1 contains idea employ here.
here's idea of i'd do:
#include <algorithm> #include <iostream> namespace mytypes { template <typename t> struct test { t a() const; void b(t t) { std::cout << t << std::endl; } }; template <> int test<int>::a() const { return 1; } template <> std::string test<std::string>::a() const { return "test"; } using testint = test<int>; using teststring = test<std::string>; } #include <boost/variant.hpp> namespace mytypes { using value = boost::variant<int, std::string>; namespace detail { struct a_f : boost::static_visitor<value> { template <typename t> value operator()(test<t> const& o) const { return o.a(); } }; struct b_f : boost::static_visitor<> { template <typename t> void operator()(test<t>& o, t const& v) const { o.b(v); } template <typename t, typename v> void operator()(test<t>&, v const&) const { throw std::runtime_error(std::string("type mismatch: ") + __pretty_function__); } }; } template <typename o> value a(o const& obj) { return boost::apply_visitor(detail::a_f{}, obj); } template <typename o, typename v> void b(o& obj, v const& v) { boost::apply_visitor(detail::b_f{}, obj, v); } } #include <vector> int main() { using namespace mytypes; using anytest = boost::variant<testint, teststring>; std::vector<anytest> list{testint(), teststring(), testint(), teststring()}; (auto = list.begin(); != list.end(); ++it) b(*it, a(*it)); }
this prints
1 test 1 test
bonus points
if insist, can wrap anytest
variant proper class , have a()
, b(...)
member functions on that:
int main() { using namespace mytypes; std::vector<anytest> list{anytest(testint()), anytest(teststring()), anytest(testint()), anytest(teststring())}; (auto = list.begin(); != list.end(); ++it) it->b(it->a()); }
Comments
Post a Comment