I'm trying to implement visitor pattern for n-ary tree mutation. Currently i'm stuck with shared pointers. Mutator operates on each tree node and can return either pointer to a node itself w/o any changes, or a pointer to a copy of modified node (original node cannot be modified directly). But obviously i can't build a shared pointer from a raw pointer inside Visit method, neither i can't make a shared pointer from this inside a Mutate method. The only idea that comes into my mind, is to create another class which will be holding pointer and pass this class pointer to visitor instead, but perhaps there is a better solution?
// Forward declarations
class ExpressionTreeMutator;
struct BaseExpr;
enum class ExpressionType {
kString,
kInt,
};
using ExprPtr = std::shared_ptr<BaseExpr>;
struct BaseExpr {
explicit BaseExpr(ExpressionType expression_type) : expression_type_(expression_type) {}
virtual ~BaseExpr() = default;
virtual ExprPtr Mutate(ExpressionTreeMutator* visitor) const = 0;
ExpressionType expression_type_;
};
// Curiously recurring template pattern
template<typename T>
struct Expr : public BaseExpr {
explicit Expr(ExpressionType expression_type) : BaseExpr(expression_type) {}
~Expr() override = default;
ExprPtr Mutate(ExpressionTreeMutator* visitor) const override;
};
struct String : public Expr<String> {
explicit String(std::string value) : Expr(ExpressionType::kString),
value_(std::move(value)) {}
std::string value_;
};
struct Int : public Expr<Int> {
explicit Int(int64_t value) : Expr(ExpressionType::kInt),
value_(value) {}
int64_t value_;
};
class ExpressionTreeMutator {
public:
virtual ~ExpressionTreeMutator() = default;
protected:
template<typename T>
friend
struct Expr;
virtual ExprPtr Visit(Int const* expr) {
// return expr ??? (in some cases return ptr as it is)
};
virtual ExprPtr Visit(String const* expr) {
// return String::Make(expr) ??? (make a copy)
};
};
template<typename T>
ExprPtr Expr<T>::Mutate(ExpressionTreeMutator* visitor) const {
return visitor->Visit(dynamic_cast<T const*>(this));
}
As it is tagged C++20, I'd suggest to use std::variant and std::visit instead.
Otherwise, you can inherit from std::enable_shared_from_this, which allows to create shared_ptr from within methods of X.
You can also use mutate not to do the actual mutation, but to return appropriate function object that does the mutation and then pass the shared_ptr to this object.
Related
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();
};
I am trying to solve a programming problem that consists of an object (call it Diagram), that contains several parameters. Each parameter (the Parameter class) can be one of several types: int, double, complex, string - to name a few.
So my first instinct was to define my Diagram class as having a vector of template parameters, which would look like this.
class Diagram
{
private:
std::vector<Parameter<T> > v;
};
This doesn't compile, and I understand why. So, based on the recommendations on this page How to declare data members that are objects of any type in a class, I modified my code to look like:
class ParameterBase
{
public:
virtual void setValue() = 0;
virtual ~ParameterBase() { }
};
template <typename T>
class Parameter : public ParameterBase
{
public:
void setValue() // I want this to be
// void setValue(const T & val)
{
// I want this to be
// value = val;
}
private:
T value;
};
class Diagram
{
public:
std::vector<ParameterBase *> v;
int type;
};
I'm having trouble figuring out how to call the setValue function with an appropriate templated parameter. It is not possible to have a templated parameter in the ParameterBase abstract base class. Any help is greatly appreciated.
P.S. I don't have the flexibility to use boost::any.
You got very close. I added a few bits because they're handy
class ParameterBase
{
public:
virtual ~ParameterBase() {}
template<class T> const T& get() const; //to be implimented after Parameter
template<class T, class U> void setValue(const U& rhs); //to be implimented after Parameter
};
template <typename T>
class Parameter : public ParameterBase
{
public:
Parameter(const T& rhs) :value(rhs) {}
const T& get() const {return value;}
void setValue(const T& rhs) {value=rhs;}
private:
T value;
};
//Here's the trick: dynamic_cast rather than virtual
template<class T> const T& ParameterBase::get() const
{ return dynamic_cast<const Parameter<T>&>(*this).get(); }
template<class T, class U> void ParameterBase::setValue(const U& rhs)
{ return dynamic_cast<Parameter<T>&>(*this).setValue(rhs); }
class Diagram
{
public:
std::vector<ParameterBase*> v;
int type;
};
Diagram can then do stuff like these:
Parameter<std::string> p1("Hello");
v.push_back(&p1);
std::cout << v[0]->get<std::string>(); //read the string
v[0]->set<std::string>("BANANA"); //set the string to something else
v[0]->get<int>(); //throws a std::bad_cast exception
It looks like your intent is to store resource-owning pointers in the vector. If so, be careful to make Diagram have the correct destructor, and make it non-copy-constructable, and non-copy-assignable.
The bellow implementation uses a few C++11 features but you will be
able to pick them apart.
#include <vector>
#include <memory>
class Parameter
{
private:
class ParameterBase {
public:
virtual ~ParameterBase() {}
virtual ParameterBase* copy() = 0;
virtual void foo() = 0;
};
template <typename T>
class ParameterModel : public ParameterBase {
public:
// take by value so we simply move twice, if movable
ParameterModel(const T& t) : t(t) {}
ParameterModel(T&& t) : t(t) {}
void foo() { t.foo(); }
ParameterModel* copy() { return new ParameterModel(*this); }
private:
T t;
};
public:
template <typename T>
Parameter(T&& t)
: pp(new ParameterModel< typename std::remove_reference<T>::type >(std::forward<T>(t))) {}
// Movable and Copyable only
Parameter(Parameter&&) = default;
Parameter& operator=(Parameter&&) = default;
Parameter(const Parameter& other) : pp(other.pp->copy()) {};
Parameter operator=(const Parameter& other) {
pp.reset(other.pp->copy());
return *this;
};
// members
void foo() { pp->foo(); }
private:
std::unique_ptr<ParameterBase> pp;
};
class Diagram
{
public:
std::vector<Parameter> v;
int type;
};
struct X {
void foo() {}
};
struct Y {
void foo() {}
};
int main()
{
Diagram d;
d.v.emplace_back(X()); // int
// parameters are copyable and can be reassigned even with different
// impls
Parameter p = d.v.back();
Parameter other((Y()));
other = p;
return 0;
}
What does this code do? It hides the fact that we use inheritance to
implement parameters from our users. All they should need to know is
that we require a member function called foo. These requirements are
expressed in our ParameterBase. You need to identify these
requirements and add the to ParameterBase. This is basically a more
restrictive boost::any.
It is also quite close to what is described in Sean Parent's value semantics talk.
I have an Interface (there missing a lot of members, but mind the fact this interface is mandatory). I will need 5 classes inheriting from it, which will have a _value attribute. So, ins\
tead of implement 5 classes(for char, short, int, float, double), I thought about a template class :
class my_interface
{
public:
virtual [various_types] getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual T getValue() const { return _value; }
};
...so that something like that could work :
void my_function()
{
my_inteface* a = new my_class<char>(42);
my_interace* b = new my_class<short>(21);
int result;
result = a->getValue() + b->getValue();
}
But I don't see how I could do. It seems you can't make templates on interface pure virtual. To me, the only way that could work would be to make getValue() to always return a double, since it is the highest sized type I need. However, I don't like that solution.
If you have just one methods (getValue()) on your interface then you only need the template class implementation.
However if you want to an interface like this:
std::string getValue();
int getValue();
long getValue();
Then you are out of luck as you cannot overload a function name based only on the return type. Alternatively you could create a wrapper type.
EDIT
By wrapper type what I mean is that if getValue is required to return multiple types you could do it in a number of ways using a wrapper class that encapsulates your required functionality rather than add it to your top level interface. It could look something like this:
enum ValType{
INT, CHAR, STR, DEQUE
};
class Wrapper{
private:
union S{
int intVal;
char charVal;
std::string stringVal;
std::deque dequeVal;
~S() {}
} theVal;
ValType heldType;
public:
void setVal(int value){ heldType = INT; theVal.intVal = value; }
void setVal(char value){ heldType = CHAR; theVal.charVal = value; }
// ... and so on
int getIntVal() const {
if(heldType!=INT)
throw std::runtime_error("Cop on");
return theVal.int;
}
// and so on
}
Then your interface is
public class my_interface{
virtual Wrapper getVal();
}
You are not really gaining much here as the user will still have to call the correct child member of Wrapper.
You could also just represent the return values as a string if you wanted.
Note that using unions you need to be careful of the caveats:
http://en.cppreference.com/w/cpp/language/union
EDIT 2:
You could do this with a templated return
template<typename = T>
const T& getVal(const T& typeToAllowMethodOverriding) const;
Remember that 'virtual ...' means "make a function pointer in the class that I will use to call the correct derived class". It is just a pointer -- so you have to agree on the return type before you call it. C++ doesn't have the dynamic types and reflection of other languages - it has to know what the return type is before making the call.
You could make class my_interface a template class as well:
template<typename T>
class my_interface
{
public:
virtual T getValue() const = 0;
};
This will generate an interface and a class for every type T that you use.
template<typename U>
class my_interface
{
public:
virtual U getValue() const = 0;
};
template<typename T>
class my_class : public my_interface<T>
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
T getValue() const { return _value; }
};
It works for all types but for string type you have to do specialization of templates
I think your best shot will be to use/implement something like boost::variant.
typedef boost::variant<char, short, int, float, double> Value;
class my_interface
{
public:
virtual Value getValue() const = 0;
};
template<typename T>
class my_class : public my_interface
{
private:
T _value;
public:
my_class(T value) : _value(value) {} // initialize the attribute on construct
virtual Value getValue() const { return _value; }
};
Then you could implement the arithmetic operators:
Value operator+(const Value &lhs, const Value &rhs) {
//Check the internal types of lhs and rhs and perform the operation
}
You can also wrap the boost::variant in another class, to provide conversion operators to the basic types.
I am having trouble in finding simple and elegant design for the following scenario. Class Worker uses template class Helper to do some work. In the simple scenario it looks like this:
template<typename T>
class Helper {
public:
void Help(T data) : m_data(data) {} //NOTICE: Copy
T const& Data() const { return m_data; }
T m_data;
}
class SimpleWorker {
public:
SimpleWorker() : m_helper(SimpleData()) {} // non-temp used in reality
void DoWork()
{
m_helper.help();
}
Helper<SimpleData> m_helper;
}
Things get complicated for me when the template argument is more complex and is of the same business domain of the worker. The worker needs to use the helper but it would also need to call some methods on the data object that the helper doesn't even know about (in this design). Something like:
template<typename T>
class Helper {
public:
Helper(T data) : m_data(data) {} //NOTICE: Copy
T const& Data() const { return m_data; }
T m_data;
}
class ComplexWorker {
public:
ComplexWorker() : m_helper(ComplexData()) {} // non-temp used in reality
void DoWork()
{
m_helper.help();
m_helper.GetData().DoSomethingComplexNotConst(); // <-------------
}
Helper<ComplexData> m_helper;
}
The obvious problem is that I can't call not const function on Data() result. Making Data() non-const seems like a bad idea as Helper is used in different contexts as well. My goal is to find an elegant way to alter ComplexData using its member functions from ComplexWorker
The ComplexData needs to be altered in the first place so that Helper can continue working with the altered data.
EDIT: Changed Helper construction to copy the provided data to better resemble actual flow
I think it's best to let Helper have only static functions, not maintaing state (as you create temporary ComplexData() in ComplexWorker in your own code). Pass the data by reference or const-reference depending on whether you need to modify or not.
// primary template
template<typename T>
class Helper {
public:
static void help(T const& data) const {} // non-modifying
};
// specialization for ComplexData
template<>
class Helper<ComplexData> {
public:
static void help(ComplexData const& data) const { } // non-modifying
static void DoSomethingComplexNotConst(ComplexData& data) // modifying
{
// your implementation here
}
};
class ComplexWorker {
public:
ComplexWorker() : m_data(ComplexData()) {} // create new data
void DoWork()
{
Helper<ComplexData>::help(m_data);
Helper<ComplexData>::DoSomethingComplexNotConst(m_data); // <--- now no problem
}
private:
ComplexData m_data;
};
Note that I made a template specialization for the ComplexData. There is some code duplication in help() but you can easily extract this into a common non-member helper function.
Seems to me that it depends on what Helper is actually doing. Your example just gives a constructor and an accessor but I doubt that is all it does in practice.
Have you considered simply using inheritance? Your Helper template would then look like this:
template<typename T>
class Helper : public T {
Helper(T data) : T(data) {}
void Help() {};
}
In this case you could use the Helper<ComplexData> object directly in an 'is-a' relationship:
class ComplexWorker {
Helper<ComplexData> m_helper;
void DoWork()
{
m_helper.help();
m_helper.DoSomethingComplexNotConst();
}
}
Why not refer to the realization of the Container part in STL. An overload of the Data() function may achieve a ballance between safty and elegance.
template <typename T>
class Helper {
public:
Helper(T data) : m_data(data) {} //NOTICE: Copy
T const& Data() const { return m_data; }
T& Data() {return m_data; }
private:
T m_data;
}
class ComplexWorker {
public:
ComplexWorker() : m_helper(ComplexData()) {} // non-temp used in reality
void DoWork()
{
m_helper.help();
ComplexData &cd1 = m_helper.Data();
cd1.QuerySth();
const ComplexData &cd2 = m_helper.Data();
cd2.ModifySth();
}
private:
Helper<ComplexData> m_helper;
}