I'm trying to create the following flow:
Having a 'Base' class, with no params or functionality, just so i can hold
Base pointers in a method.
Its derived class, is a template, which implements operator() on given template argument object type.
I'm trying, by using a pointer to base class, call the derived class operator(), in run-time.
I've tried implementing it using CRTP
(https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern)
But that doesn't seem to work the-other-way-around - when the derived class is a class template.
Here is my code:
class Base {};
template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base {
private:
typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
Func_p m_func;
const Ref_Obj& m_db;
public:
Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}
inline bool operator()(const Obj_Type& obj) const {
return (m_db.*m_func)(obj);
}
}
Now, usage is in another class template, that contains vector of Base class pointers, as follows, and have its own operator() :
template<typename Obj_Type2> /* Upon usage, Obj_Type2 is the same as Obj_Type, this is just to differ the two in the code here */
class BlaBla {
private:
std::vector<const Base *> m_vec;
public:
/* relevant constructors ... */
inline bool operator()(const Obj_Type2 &obj) const {
for(std::vector<const Base *>::const_iterator it = m_vec.begin(); it != m_vec.end(); ++it) {
/*** This is the problematic line V ***/
if( (*it).operator()(obj) ) { /* DO SOMETHING */ }
}
}
Of course the compiler is complaining that there is no matching function to call for in the problematic line that is marked in the code below, but i can't figure out a way to do the relevant call.
1st Solution that came to mind, is to create a virtual operator()(...), with a specific object type e.g. virtual operator()(const uint32_t &obj) in Base class, which works, but my intention is that operator()(...) will receive a variety of object types, and stating a virtual method for each of them is not elegant and seems to break all the template concept i want to implement here.
2nd Solution that came to mind, is somehow passing Ref_Obj and Obj_Type typenames to Base class, to be used in sort of interface method, that will use static_cast to call the appropriate Derived operator (As in CRTP) - But that doesn't seem to work because Derived class is a class template, and also BlaBla class doesn't directly know Ref_Obj typename.
Is there any other way to make the appropriate call to Deriver operator()
There is no clear clean way to do this. The fundamental problem is that there is no such thing as a virtual template method.
The cleanest way I can think of doing this that implements complete type erasure is with a dynamic cast, and a virtual method:
class Base {
public:
virtual bool operator()(const Base &) const=0;
};
template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base {
private:
typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
Func_p m_func;
const Ref_Obj& m_db;
public:
Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}
inline bool operator()(const Base& obj) const override {
const Obj_Type *derived_obj=dynamic_cast<const Obj_Type *>(&obj);
if (!derived_obj)
{
throw; // Or maybe return false, or something...
}
return (m_db.*m_func)(*derived_obj);
}
};
Obj_Type must also be derived from Base. This gets the job done at runtime, but there is no compile-time type-checking.
The other approach is to bite the bullet, and forego 100% type erasure:
template<typename Obj_Type>
class Base {
public:
virtual bool operator()(const Obj_Type &) const=0;
};
template<typename Ref_Obj, typename Obj_Type>
class Derived : public Base<Obj_Type> {
private:
typedef bool (Ref_Obj::*Func_p)(Obj_Type) const;
Func_p m_func;
const Ref_Obj& m_db;
public:
Derived<Ref_Obj, Obj_Type>(const Ref_Obj& db, Func_p func): m_db(base), m_func(filter) {}
inline bool operator()(const Obj_Type& obj) const override {
return (m_db.*m_func)(obj);
}
};
So, you can still abstract away operator() on some object to its pure interface, and define the details in the subclass.
Or, another alternative would be a combination of the two:
class SuperBase {
public:
virtual bool operator()(const Base &) const=0;
};
template<typename Obj_Type>
class Base : public SuperBase {
public:
virtual bool operator()(const Obj_Type &) const=0;
bool operator()(const Base &obj) const override
{
// Do the dynamic cast check, and forward it to the other
// operator().
}
};
Related
I have a base class called ISignalFilter and I want to create derived classes such that all the derived classes can use an operator overload * to combine into another derived class called ProductFilter.
The problem is, product filter stores the base class and calls the base class method filtered_value. I want the ProductClass to call the derived class method filtered_value. How would I do this?
#include <iostream>
using namespace std;
template <typename T>
class ISignalFilter;
template <typename F>
class ProductFilter;
template <typename T>
class ISignalFilter {
public:
virtual T filtered_value(const T& value) {
(void)value;
std::cout<<"Error this should not be called."<<std::endl;
// BOOST_LOG_TRIVIAL(error) << "Base case usage of method not allowed";
std::abort();
};
virtual ProductFilter<T> operator*(ISignalFilter<T>& other) {
return ProductFilter<T>(*this, other);
}
};
template <typename F>
class ProductFilter : public ISignalFilter<F> {
public:
ProductFilter(const ISignalFilter<F>& a, const ISignalFilter<F>& b) {
a_ = a;
b_ = b;
}
F filtered_value(const F& value) override {
return b_.filtered_value(a_.filtered_value(value));
}
ISignalFilter<F> a_;
ISignalFilter<F> b_;
};
template <typename T>
class IdentityFilter : public ISignalFilter<T> {
public:
IdentityFilter() {}
T filtered_value(const T& value) override { return value; }
};
int main() {
auto filter1 = IdentityFilter<int>();
auto filter2 = filter1 * filter1;
std::cout<<filter2.filtered_value(1)<<std::endl; //should output one.
return 0;
}
Let's play with non-template classes to resolve your title question.
My suggestion is to use different named methods:
class Base
{
public:
bool operator==(const Base& other) const
{
return equal_to(other);
}
protected:
virtual bool equal_to(const Base& other) const = 0;
};
In the above code fragment, the operator== is redirected to call a method, equal_to which is tagged so that child classes must implement it.
Whether derived classes use the operator== or call equal_to is up to the coder.
Note: for best results, overloading operator== should be in each derived class. See also "object slicing".
the main problem, as #user253751 said in comment, is you need to store reference/pointer for dynamic polymorphism to work.
there are some other thing to change
mark the method const (or accept non-const for ProductFilter constructor)
the operator can be defined outside of ISignalFilter, and as it's actually a functionality of ProductFilter, it's reasonable to do it.
use pure virtual function (=0) to catch error at compile time (and your code actually would shows error because you cannot create instance of ISignalFilter<T>)
you probably also want to return const T& for filtered_value
the final code
template <typename T>
struct ISignalFilter {
virtual T filtered_value(const T& value) const = 0;
};
template <typename T>
struct ProductFilter : ISignalFilter<T> {
ProductFilter(const ISignalFilter<T>& a, const ISignalFilter<T>& b)
:a(a),b(b){}
T filtered_value(const T& value) const override {
return b.filtered_value(a.filtered_value(value));
}
const ISignalFilter<T> &a, &b;
};
template<typename T>
ProductFilter<T> operator*(const ISignalFilter<T>& a, const ISignalFilter<T>& b) {
return ProductFilter<T>(a,b);
}
https://godbolt.org/z/oxxKx9z4z
I'm trying to override an inherited function from a base class which is also a class template, but I can't get it to work.
Up to now the base class is:
template<typename T, typename instrument>
class Probe {
private:
instrument probe;
public:
Probe(instrument _probe) : probe{_probe} {}
virtual T read() const;
instrument getProbe() const {return this->probe;}
};
While the derived class is:
class TestProbe : public Probe<int,int> {
public:
TestProbe(int _probe) : Probe(_probe) {}
virtual int read() const override {return getProbe();} // later will have a more complex expression
};
The error I get whenever I try to compile is: undefined reference to Probe<int, int>::read() const
How do I ensure my derived class implements at least one of two chosen methods in the base class?
class base {
public:
virtual int sample()=0;
virtual Eigen::VectorXf sample()=0;
};
class Derived : Base {
int sample() override {return 1;}
}
This code returns an error, as the sample method is not implemented with the VectorXf return type. However, my intention is that only one of these need to be implemented. The only reason they are seperate in the base class is that they have different return type. How can I do this in C++?
Overloading by return type is not possible. You may use std::variant instead:
#include <variant>
class Base {
public:
virtual std::variant<int, Eigen::VectorXf> sample()=0;
};
class Derived : public Base {
std::variant<int, Eigen::VectorXf> sample() override {return 1;}
};
If one is restricted to C++11, then there are many alternatives.
Implement and use something like variant: a class that has a enumerator selecting between two active types, and a union to contain these types.
Use Boost variant.
std::pair
Implement a hierarchy of classes (a simplification of std::any), and return on the right pointer to object:
class AbstractBase {
public:
virtual ~AbstractBase() = 0;
template <class T>
const T* get() const;
};
template <class T>
class ValueWrapper : public AbstractBase {
public:
ValueWrapper(const T& value) : m_value(value) {}
const T & getValue() const { return m_value; }
private:
T m_value;
};
template <class T>
inline const T * AbstractBase::get() const {
auto child = dynamic_cast<ValueWrapper<T> const*>(this);
return child ? &child->getValue() : nullptr;
}
class Base {
public:
virtual std::unique_ptr<AbstractBase> sample()=0;
};
The question is, why would you need this?
I need to have a map holding different value types. I achieved that using a derived template class Derived of type T derived from B and declaring my map using a pointer to the base class Base like so:
class Base {
public:
~Base(){}
};
template <class T>
class Derived: public Base {
public:
Derived(T value) {
this->value = value;
}
T value;
};
std::map<std::string, std::shared_ptr<Base>> my_map;
using KeyValuePair = std::pair<std::string, std::shared_ptr<Base>>;
my_map.insert(KeyValuePair("foo1",std::make_shared<Derived<int>>(10)));
my_map.insert(KeyValuePair("foo2",std::make_shared<Derived<double>>(20.0)));
my_map.insert(KeyValuePair("foo3",std::make_shared<Derived<std::string>>("bla")));
I now for example want to print the value of a map entry
for (auto const& x : my_map)
{
std::cout << *x.get() << std::endl;
}
However, I now have the problem that I cannot access the the members in the Derived class by casting x to Derived, because I don't know the type of the template parameter. So the following is not possible:
std::shared_ptr<Derived<?>> derived = std::dynamic_cast<Derived<?>>(x);
I thought about having a virtual function in the Base class which returns the member, but I don't know the return type, so not an option.
I also don't want to specify several virtual functions for several return types, as the whole point of the code is to avoid copying code and having a "generic map"
However, I don't see another solution besides using some fancy boost magic by returning a streamable boost::any like the following, as this removes any information about the type.
using streamable_any = boost::type_erasure::any<boost::mpl::vector<
boost::type_erasure::copy_constructible<>,
boost::type_erasure::destructible<>,
boost::type_erasure::ostreamable<>>>;
What are the possibilities I have to achieve what I want? I suspect that I need to consider a design change.
Specifically for printing, you can add a single virtual method easily enough:
class Base {
public:
virtual ~Base() {}
virtual std::ostream& print(std::ostream&) const = 0;
friend std::ostream& operator<<(std::ostream& os, Base const &b) {
return b.print(os);
}
};
template <class T>
class Derived: public Base {
T value;
public:
Derived(T v) : value(v) {}
std::ostream& print(std::ostream& os) const override {
return os << value;
}
};
However, if you need more general access to the value, your options are essentially:
Extract value as Boost.any (by virtual function)
Enumerate all legal types for T, and return a Boost.variant<Ts> (again by virtual function)
Enumerate all legal types and write a Visitor with overloads for each. Then implement a simple virtual visit method in Base and Derived. Note that Derived<T>::apply(Visitor &v) { v.visit(value); } will fail to compile if T doesn't match any overload of visit, and also that you need to take care when the valid types of T have implicit conversions.
You can avoid coupling your code to a pre-defined list of legal Ts by writing a post-hoc visitor. This means manual dispatch, looking up the function to call using std::type_index as your key, and manual casting. It's ugly though.
Or (worst but most flexible) keep the streaming output and just re-parse the value from a stringstream. If you must do this, consider serializing to a well-defined format instead of (or as well as) just writing a pretty human-readable format.
First of all you have UB in your example, as you hold instances of derived classes through pointer of base, destructor must be virtual.
To fix your current problem with printing values you can add a virtual method:
class Base {
public:
virtual void print( std::ostream &os ) const = 0;
virtual ~Base(){}
};
but that would only fix this particular problem, but accessing values would be still issue. One of solution would be to add a virtual getter that converts all values to std::string. Or always use cascade of dynamic_cast<> (note dynamic cast would require at least one virtual method in Base). But better to use boost::variant which provides functionality to implement visitor pattern and check if this instance holds value of particular type. You would not need inheritance at all in this case.
Getting:
template<class...Ts>
struct types {};
template<class types, template<class...>class>
struct apply_to {};
template<class types, template<class...>class Z>
using apply_to_t=typename apply_to<types, Z>::type;
template<class...Ts, template<class...>class Z>
struct apply_to<types<Ts...>, Z>{ using type=Z<Ts...>; };
template<class types>
using variant_of=apply_to_t<types, boost::variant>;
using supported_types = types<int, double, std::string>;
class Base {
virtual variant_of_t<supported_types> get() const = 0;
protected:
~Base() {}
};
template<class T>
class Derived final: public Base {
T t;
public:
virtual variant_of_t<supported_types> get() const override {
return t;
}
virtual ~Derived() {}
};
Setting can be a bit trickier.
template<class...Ts>
using sink = boost::variant< std::function<void(Ts)>... >;
template<class types>
using setters = apply_to_t<types, sink>;
class Base {
virtual variant_of_t<supported_types> get() const = 0;
virtual void set( std::function<void(setters<supported_types>)> ) = 0;
protected:
~Base() {}
};
template<class T>
class Derived final: public Base {
T t;
public:
virtual void set( std::function<void(setters<supported_types>)> s ) override {
s( std::function<void(T)>( [&](T&& in) { t = std::forward<T>(in); } ) );
}
virtual variant_of_t<supported_types> get() const override {
return t;
}
virtual ~Derived() {}
};
which is a bit more insane.
This gives you type-safe get and set. When you call set, you must pass in a lambda that can accept any type setter, and do the right thing. When you call get, it returns a variant over the possibilities of the contained data, which you have to deal with.
Printing would look like:
for (auto const& x : my_map)
{
if (!x) continue;
boost::apply_visitor([&](auto&& x){
std::cout << x << std::endl;
}, x->get());
}
Suppose you want to set a value.
template<class...Fs>
struct override_t;
template<class F0, class F1, class...Fs>
struct override_t<F0, F1, Fs...>: F0, override_t<F1, Fs...> {
using RBase=override_t<F1, Fs...>;
using F0::operator();
using RBase::operator();
override_t( F0 f0, F1 f1, Fs... fs ):
F0(std::move(f0)),
RBase(std::move(f1), std::move(fs)...)
{}
};
template<class F0>
struct override_t<F0>: F0 {
using F0::operator();
override_t( F0 f0 ):
F0(std::move(f0))
{}
};
template<>
struct override_t<> {};
template<class...Fs>
override_t<Fs...> override( Fs... fs ) { return {std::move(fs)...}; }
x->set(
[&]( auto setters ) {
boost::apply_visitor(
override(
[&]( std::function<void(int)> set ) {
set(7);
},
[&]( auto&& ) {
assert(false); // wrong type
}
),
setters
);
}
);
as type-safe setting of a value with unknown type is rather difficult to get right.
One option would be to make the class B a template, so it could have a method that returns a value of type T:
template <class T>
class Base {
public:
virtual T GetValue();
};
Another option is to have a virtual print method:
class Base {
public:
virtual void PrintValue();
};
This is somewhat hypothetical as I'm not too worried about performance - just wondering which option is actually the fastest/most efficient in general, or if there is no difference whatsoever.
Suppose I have the following code for a visitor template that supports overloading:
#define IMPLEMENT_VISITOR_WITH_SUPERCLASS(superclass) \
typedef superclass visitor_super_t; \
virtual void visit(Visitor& v) { v.visit(*this); }
//-----------------------------------------------------------------------------
// Implementation detail:
// Selective dispatcher for the visitor - required to handle overloading.
//
template <typename T>
struct VisitorDispatch {
static void dispatch(Visitor* v, T* t) { v->visit(*t); }
};
// Specalization for cases where dispatch is not defined
template <> struct VisitorDispatch<void> {
static void dispatch(Visitor* v, void* t) { throw std::bad_cast(""); }
};
//-----------------------------------------------------------------------------
// Derive visitors from this and 'Visitor'.
template <typename T>
class VTarget
{
public:
// Don't really need a virtual dtor.
virtual void dispatch(T& t) = 0;
};
//-----------------------------------------------------------------------------
class Visitor
{
public:
virtual ~Visitor() = 0;
template <typename T>
void visit(T& t) {
typedef VTarget<T> target_t;
target_t* tgt = dynamic_cast<target_t*>(this);
if (tgt) {
tgt->dispatch(t);
}
else {
// Navigate up inhertiance hierarchy.
// requires 'super' to be defined in all classes in hierarchy
// applicable to this visitor.
typedef typename T::visitor_super_t super;
super* s = static_cast<super*>(&t);
VisitorDispatch<super>::dispatch(this, s);
}
}
};
//-----------------------------------------------------------------------------
inline Visitor::~Visitor() {}
This is then used to create generic visitors:
class CommonBase {
IMPLEMENT_VISITOR_WITH_SUPERCLASS(void)
virtual ~CommonBase() = 0;
};
class A : public CommonBase {
IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};
class B : public CommonBase {
IMPLEMENT_VISITOR_WITH_SUPERCLASS(CommonBase)
};
class MyVisitor
: public Visitor
, public VTarget<CommonBase>
, public VTarget<A>
, public VTarget<B>
{
public:
virtual void dispatch(CommonBase& obj);
virtual void dispatch(A& obj);
virtual void dispatch(B& obj);
};
Using the visitor ultimately results in dynamic_cast<>'s from Visitor to VTarget<T>, which is a cross-cast.
The other way this could be implemented is to make Visitor a virtual base of VTarget<T> - MyVisitor would then not need to inherit directly from Visitor anymore.
The dynamic_cast<> in the Visitor::visit code would then result in a down-cast from the virtual base, Visitor.
Is one method faster than the other when performing the casts? Or do you only get a size penalty for having the virtual base?
Well, it looks like the cross-cast method is faster than the virtual base method.
With a visitation that requires 1 fallback to a superclass, over 100000000 iterations, the cross-cast method took 30.2747 seconds, and the virtual base method took 41.3999 - about 37% slower.
With no fallback to an overload for a superclass, the cross-cast was 10.733 seconds and the virtual base 19.9982 (86% slower).
I was more interested to know how the dynamic_cast would operate in either mode, really.