Adding member functions to a Boost.Variant - c++

In my C++ library I have a type boost::variant<A,B> and lots of algorithms getting this type as an input. Instead of member functions I have global functions on this type, like void f( boost::variant<A,B>& var ). I know that this can also be achieved with templates, but this is not suitable for my design.
I am very fine with this style of programming:
boost::variant<A, B> v;
f( v );
but some of the users of this library are not used to it, and since the Boost.Variant concept is hidden by a type definition, they feel like calling v.f().
To achieve this, I can think of two possibilities: 1) overriding from boost::variant and 2) re-implementing boost::variant and adding my own member functions. I am not sure whether these ideas are good or not. Can you give me some help with this please? Are there other possibilities?

Another possibility: Use aggregation. Then you do not directly expose the boost.variant to the users of the library, giving you way more freedom for future improvements, and may simplify some debugging tasks by a significant amount.
General Advice:
Aggregation is less tightly coupled than inheritance, therefore better by default, except you know a use-case where you explicitly want to pass your object instance to already existing functions only taking variants. And even than the base class should have been designed with inheritance in mind.
Example for Aggregation for Your Problem:
As far as I understand it, the free functions already exist, and take a variant. Just define a class with the sole data member of the variant, and provide public member functions which do nothing but invoke the already existing free functions with the member variant, like
class variant_wrapper {
boost::variant<A,B> m_variant;
public:
variant_wrapper(...) : m_variant(...) {} // whatever c_tor you need.
void f() { f(m_variant); }
};
Using this approach you abstract away the fact that you are using boost.variant for your implementation (which you already do through a typedef for the library's users), giving you the freedom of later changing that (for optimization or feature extensions or whatever), you can decide to make the values immutable, have a more simple approach to debug accesses to your algorithms, etc. etc..
The disadvantage with the aggregation is that you cannot just pass the wrapper to a static_visitor, but as your users shall not know that there is a variant, and you know to simply pass the member variable, I do not see a big issue here.
Final rant:
C++ is not Java. You need to fix the users of the library...
What you would like to have are C# extension methods; such things do not exist in C++. However, I would not reimplement/implementation-copy boost.variant (maintenance burden), and I would not inherit from it. Use aggregation where possible.

I'd derive from boost::variant. That should be fine so long as you dont add data members to the class, and don't add virtual functions. (You may be able to do some of those but things are a little more iffy I think). Anyway this seems to work OK for me.
#include "boost/variant.hpp"
#include <iostream>
template<typename T1, typename T2>
struct my_print : public boost::static_visitor<>
{
void operator()( T1 t1 ) const
{
std::cout<<"FIRST TYPE "<<t1<<std::endl;
}
void operator()( T2 t2 ) const
{
std::cout<<"SECOND TYPE "<<t2<<std::endl;
}
};
template<typename T1, typename T2>
class MyVariant : public boost::variant<T1,T2>
{
public:
void print()
{
boost::apply_visitor(my_print<T1,T2>(), *this );
}
template<typename T>
MyVariant<T1,T2>& operator=(const T& t)
{
boost::variant<T1,T2>::operator=(t);
return *this;
}
MyVariant(const T1& t) : boost::variant<T1,T2>(t)
{
}
MyVariant(const T2& t) : boost::variant<T1,T2>(t)
{
}
template<typename T>
explicit MyVariant(const T& t) : boost::variant<T1,T2>(t)
{
}
};
int main()
{
MyVariant<int,std::string> s=1;
s.print();
s=std::string("hello");
s.print();
MyVariant<int,std::string> v2 = s;
v2.print();
s=boost::variant<int,std::string>(3);
s.print();
}

Related

Storing templated objects in a vector (Storing Class<int>, Class<double> in a single vector)

There is a templated class, let it be
template<typename T> class A { std::vector<T> data; };
The problem I am facing here is, users can create several types of this class, but I need to track them, best case is I have a reference of these objects in another vector, but that would not work since all types are different.
Can you recommend a good design pattern which can encapsulate this.
I can store pointers and then typecast it, but its not elegant.
I can change the architecture as well, if the solution provided is good enough.
The basic question I am trying to solve is, I have a class of vector of custom types, how do I store them.
As previous comments stated - you first need to make sure this is what you need.
With that been said, I had a similar requirement in a project of mine, which I eventually solved with inheritance and PIMPL, as follows:
class A{
private:
struct Abstract {
virtual void f() = 0;
};
template <typename T>
struct Implementation : public Abstract {
std::vector<T> data;
virtual void f() {...}
};
std::unique_ptr<Abstract> impl;
public:
template <typename T>
A(): impl(std::make_unique<Implementation<T> >()){}
void f() {impl->f();}
};
This allows you to create a container of objects of type A, and access them via the public interface defined therein (the method f). The underlying type T of each A object is specified on construction. All other implementation details specific to the type T are hidden.
The solution suffers the inherent overhead of virtual functions. I'm not sure how it compares to the std::any approach performance-wise.
std::any is the modern c++17 solution. Specifically, you should use
A<int> a;
a.data.push_back(0);
// fill refernces...
std::vector<std::any> refernces;
refernces.push_back(&a.data[0]);
// check which type is active.
if(int** iPtr = std::any_cast<int*>(&references[0]); iPtr != nullptr)
{
// its an int*
int& i = **iPtr;
// do something with i.
}
These pointers can point into the A<int>::data and A<double>::data vectors.
For a complete reference, see here https://en.cppreference.com/w/cpp/utility/any.

Refactoring out method common to all classes

I've got a global function that copies relevant bits of one object (or type Source) to another (of type Target), like so:
template<typename Source , typename Target>
void partialCopy( Source& source , Target& target )
{
// perform copy
}
The problem I find with global functions is that, unlike member functions, it is not instantly clear when coding which of the two arguments is the source and which is the target. Therefore I would like to have a member function partialCopy() in every class like so:
struct Foo
{
template<typename T>
void partialCopy( T& target )
{
::partialCopy( *this , target );
}
};
The problem now is that the member function has to be copied to dozens of classes. Is this a tolerable case of copy and paste programming? I've considered putting partialCopy in a header file partialCopy.h and using the preprocessor include to 'inject' it into each class, like so:
struct Foo
{
#include "partialCopy.h"
};
Foo f;
Bar b;
f.partialCopy( b );
Although this works I've never seen it done anywhere and don't know if its unacceptable.
I've already tried putting the partialCopy member function in a common base class and inheriting it but this doesn't work because the this keyword would then refer to the base class and not the derived class.
Is there an even better alternative? Please advise.
Edit
John's suggestion(in a thread that's been deleted) that I perform a static_cast to the derived class in a CRTP base class works nicely. #John please post this an answer and I will mark it as such.
I am posting this as an answer, because in my opinion it's appropriate. Henrik commented first, though. (However, this was also my first thought :))
const-reference
Use const& (const-reference) for source parameter. That way it's easily distinguishable from the target.
The added benefit is that it will verify and ensure const-correctness of your partial-copy function.
rvalue-reference
You might also think about overloading it for Source&&. If there are some buffers that are copied directly, your function might take use of it.
I would suggest overloading the stream operators for this.
E.g.
template<typename Source , typename Target>
void partialCopy(Source& source, Target& target)
{
// perform copy
}
effectively becomes:
template<typename Source , typename Target>
void operator>>(const Source& source, Target& target)
{
// perform copy
}
(also note that the Source parameter is now a const&, for clarity.
So you could simply write
Foo f;
Bar b;
f >> b;
Makes it much clearer what the source and target objects are.
I'm a bit late with this answer, but I thought you might be interested in a solution using CRTP as a clean alternative to copy-paste programming:
The problem now is that the member function has to be copied to dozens of classes. Is this a tolerable case of copy and paste programming? I've considered putting partialCopy in a header file partialCopy.h and using the preprocessor include to 'inject' it into each class [...].
Instead of copying or #including the code, consider the following:
// common code:
<template typename T>
class PartialCopyImplementer
{
public:
template<typename D>
void partialCopy(D& destination)
{
// ::partialCopy( *this , target );
}
};
// concrete implementations
class Foo1 : public PartialCopyImplementer<Foo1> // CRTP implementation
{
// ...
};
// concrete implementations
class Foo2 : public PartialCopyImplementer<Foo2> // CRTP ensures Foo1 and Foo2
// do not have a common base
{
// ...
};
The cleanest way would probably just be to leave partialCopy as a free function an use it that way. There is nothing inherently wrong with that, for example all the function in the standard libraries <algorithm> header are free function that will be used with objects.
It is also not really much clearer which of foo.partialCopy(bar) is the source and which the destination. Does partialCopy copy from or to bar? Generally it is useful to look at the documentation / function declaration in such cases. If you have clear names for the parameters and make them const when appropriat,e it should be pretty clear which way the objects get copied.
What about:
template<class T>
struct from_impl
{
T const& from;
from_impl(T const& f)
: from(f)
{}
};
template<class T>
from_impl<T> from(T const& f) {
return from_impl(f);
}
template<class T>
struct to_impl
{
T& to;
to_impl(T& t)
: to(t)
{}
};
template<class T>
to_impl<T> to(T& t) {
return to_impl(t);
}
template<class T>
void to(T const&); // prevent using with non-const values
template<class Source,class Target>
void partial_copy(from_impl<Source> source, to_impl<Target> target)
{
// use source.from and target.to to perform copy
}
// usage:
T1 object1;
T2 object2;
partial_copy(from(object1),to(object2));
This makes very clear what you want to do. from_impl and to_impl work like a kind of reference and from and to work as factory functions for easy usage. You could also try to implement something like.
partial_copy.from(Source).to(Target);
partial_copy(Source)->_(Target);
But normaly this is a lot of writing. Simply put partial_copy in its own namespace to prevent name clashes, let users make their own overload for customisation and use const& for signaling what source and destination are.

C++ Templates - Having generic methods for templated types

I'm starting working with C++ templates just because I wanted to understand specific differences with other languages (Java) and I reached a point in which they started to diverge but I'm not getting how I am supposed to solve the specific problem (or get around it).
Suppose I have a generic value class, eg
template <class T>
class Value
{
protected:
T value;
public:
Value(Type type, T value) : type(type), value(value) {}
void set(T value) { this->value = value; }
T get() const { return this->value; }
T clone() { return new Value<T>(type, value); }
virtual string svalue() const = 0;
const Type type;
};
and a specific subtype:
class Int : public Value<int>
{
public:
Int(int value) : Value<int>(INT, value) { };
virtual string svalue() const { ... }
friend ostream& operator<<(ostream& os, const Int& v);
};
(I know it is also possible to specify type specific code by using template <> but since I still need to use it enough to understand it I just defined by own Int class for now, which is nothing more that a typedef Value<int> in the end)
Is it possible to have, let's say, a collection that is able to store arbitrary pointers to Value instances? Without the need of specifying the specific concrete type of the generic class.
From what I understand templates are just a compile time issue for which the compiler analyzes all the concrete types for which the template is used and compiles different versions of the same methods for each of them, thus what I'm trying to do doesn't seem to be possible (while in Java I am allowed to use wildcards for something like List<Value<?>>). Am I wrong?
Is there a common design to solve this issue or I am forced to drop templates to achieve it?
#include <iostream>
#include <memory>
class Base
{
public: virtual void Print() = 0;
};
template<typename T>
class Derived : public Base
{
T V;
public:
void Print() { std::cout << V; }
Derived(T v) : V(v) { }
};
int main()
{
std::unique_ptr<Base> Ptr (new Derived<int>(5));
Ptr->Print();
return 0;
}
I think it's pretty self-explanatory.
Is it possible to have, let's say, a collection that is able to store
arbitrary pointers to Value instances?
No, not in the way you seem to want. This is not possible:
template <class T>
class Value
{
// ...
};
vector<Value> my_values_;
This isn't possible because Value isn't a type -- it's really just a blueprint, and idea, if you will. Philisophical ramblings aside, you can't store ideas, you can only store things. A Value isn't a thing.
If this is what you want, then templates might be the wrong tool for the job. Wheat you might really be after are Abstract Base Classes in which the base class (say, class Value) defines the interface and the subclasses (say, class Int : public Value) define concrete types. That way, you can create containers of generic Values, using pointers:
vector<Value*> my_values_;
Or, better yet using smart pointers:
vector<unique_ptr<Value>> my_values_;
The Java technique can be done in C++ via a mixture of a common base class (see other answer by Bartek) and techniques like type erasure.
The C++ version, where values are actually values, cannot be done in Java. It can be done in some languages that compile to Java byte code if I recall correctly.
In Java the only objects you can get ahold of are actually more like garbage collected pointers to objects in C++. Actual instances of actual objects being directly stored or referred to is verbotin, because that gets in the way of Java style garbage collection.
So a container of Value<?> in Java is analogous to a container of pointers to a common base class of all Value types that is garbage collected in C++. Access to each instance then involves a dynamic_cast or static_cast equivalent in Java.
For a more Java esque behavior, give Value a common base with a virtual trivial destructor, pure virtual common methods that have the same signature over all instances, template version that implements things with different signatures, and factory functions that produce shared_ptr s to Value instances.
Use containers of shared_ptr to the Value base and use the dynamic shared ptr cast to get particular interfaces if you need them.
Now all of that means your code is 10 to 100 times slower than without all that structure, but it may still be faster than the equivalent Java version. And you have the option to not use it if you do not need it.
I always love to confuse matters and throw in a nice syntactic twist although it still just does the same (using a common base class). The only odd bit is that the base class of Value<T> is spelled Value<> and can be used as such in a container (although not directly, of course, since you need use a point to avoid slicing):
#include <memory>
#include <vector>
template <typename T = void>
class Value;
template <>
class Value<void>
{
public:
virtual ~Value() {}
};
template <typename T>
class Value
: public Value<>
{
T value_;
public:
Value(T value): value_(value) {}
// whatever
};
template <typename T>
std::unique_ptr<Value<T>> make_value(T value) {
return std::unique_ptr<Value<T>>(new Value<T>(value));
}
int main()
{
std::vector<std::unique_ptr<Value<>>> values;
values.push_back(make_value(0));
values.push_back(make_value(0.0));
values.push_back(make_value(false));
}
Is it possible to have, let's say, a collection that is able to store
arbitrary pointers to Value instances?
No, it wouldn't work. However, there are at least to possibilities:
If you know beforehand every type you going to use in list, you can use boost::variant
You may make list of pointers to objects (actually void* or you may drop templates and make Value as base class) and somehow (e.g. dynamic_cast) cast them to some specific objects.

Should I prefer mixins or function templates to add behavior to a set of unrelated types?

Mixins and function templates are two different ways of providing a behavior to a wide set of types, as long as these types meet some requirements.
For example, let's assume that I want to write some code that allows me to save an object to a file, as long as this object provides a toString member function (this is a rather silly example, but bear with me). A first solution is to write a function template like the following:
template <typename T>
void toFile(T const & obj, std::string const & filename)
{
std::ofstream file(filename);
file << obj.toString() << '\n';
}
...
SomeClass o1;
toFile(o1, "foo.txt");
SomeOtherType o2;
toFile(o2, "bar.txt");
Another solution is to use a mixin, using CRTP:
template <typename Derived>
struct ToFile
{
void toFile(std::string const & filename) const
{
Derived * that = static_cast<Derived const *>(this);
std::ofstream file(filename);
file << that->toString() << '\n';
}
};
struct SomeClass : public ToFile<SomeClass>
{
void toString() const {...}
};
...
SomeClass o1;
o.toFile("foo.txt");
SomeOtherType o2;
o2.toFile("bar.txt");
What are the pros and cons of these two approaches? Is there a favored one, and if so, why?
The first approach is much more flexible, as it can be made to work with any type that provides any way to be converted to a std::string (this can be achieved using traits-classes) without the need to modify that type. Your second approach would always require modification of a type in order to add functionality.
Pro function templates: the coupling is looser. You don't need to derive from anything to get the functionality in a new class; in your example, you only implement the toString method and that's it. You can even use a limited form of duck typing, since the type of toString isn't specified.
Pro mixins: nothing, strictly; your requirement is for something that works with unrelated classes and mixins cause them to be become related.
Edit: Alright, due to the way the C++ type system works, the mixin solution will strictly produce unrelated classes. I'd go with the template function solution, though.
I would like to propose an alternative, often forgotten because it is a mix of duck-typing and interfaces, and very few languages propose this feat (note: very close to Go's take to interfaces actually).
// 1. Ask for a free function to exist:
void toString(std::string& buffer, SomeClass const& sc);
// 2. Create an interface that exposes this function
class ToString {
public:
virtual ~ToString() {}
virtual void toString(std::string& buffer) const = 0;
}; // class ToString
// 3. Create an adapter class (bit of magic)
template <typename T>
class ToStringT final: public ToString {
public:
ToStringT(T const& t): t(t) {}
virtual void toString(std::string& buffer) const override {
toString(buffer, t);
}
private:
T t; // note: for reference you need a reference wrapper
// I won't delve into this right now, suffice to say
// it's feasible and only require one template overload
// of toString.
}; // class ToStringT
// 4. Create an adapter maker
template <typename T>
ToStringT<T> toString(T const& t) { return std::move(ToStringT<T>(t)); }
And now ? Enjoy!
void print(ToString const& ts); // aka: the most important const
int main() {
SomeClass sc;
print(toString(sc));
};
The two stages is a bit heavyweight, however it gives an astonishing degree of functionality:
No hard-wiring data / interface (thanks to duck-typing)
Low-coupling (thanks to abstract classes)
And also easy integration:
You can write an "adapter" for an already existing interface, and migrate from an OO code base to a more agile one
You can write an "interface" for an already existing set of overloads, and migrate from a Generic code base to a more clustered one
Apart from the amount of boiler-plate, it's really amazing how you seamlessly pick advantages from both worlds.
A few thoughts I had while writing this question:
Arguments in favor of template functions:
A function can be overloaded, so third-party and built-in types can be handled.
Arguments in favor of mixins:
Homogeneous syntax: the added behavior is invoked like any other member functions. However, it is well known that the interface of a C++ class includes not only its public member functions but also the free functions that operates on instances of this type, so this is just an aesthetic improvement.
By adding a non-template base class to the mixins, we obtain an interface (in the Java/C# sense) that can be use to handle all objects providing the behavior. For example, if we make ToFile<T> inherits from FileWritable (declaring a pure virtual toFile member function), we can have a collection of FileWritable without having to resort to complicated heterogeneous data structures.
Regarding usage, I'd say that function templates are more idiomatic in C++.

given abstract base class X, how to create another template class D<T> where T is the type of the class deriving from X?

I want to be able to accept a Message& object which references either a Message1 or Message2 class. I want to be able to create a MessageWithData<Message1> or MessageWithData<Message2> based on the underlying type of the Message& object. For example, see below:
class Message {};
class Message1 : public Message {};
class Message2 : public Message {};
template<typename Message1or2>
class MessageWithData : public Message1or2 { public: int x, y; }
class Handler()
{
public:
void process(const Message& message, int x, int y)
{
// create object messageWithData whose type is
// either a MessageWithData<Message1> or a MessageWithData<Message2>
// based on message's type.. how do I do this?
//
messageWithData.dispatch(...)
}
};
The messageWithData class essentially contains methods inherited from Message which allow it to be dynamically double dispatched back to the handler based on its type. My best solution so far has been to keep the data separate from the message type, and pass it all the way through the dynamic dispatch chain, but I was hoping to come closer to the true idiom of dynamic double dispatch wherein the message type contains the variable data.
(The method I'm more or less following is from http://jogear.net/dynamic-double-dispatch-and-templates)
You're trying to mix runtime and compile-time concepts, namely (runtime-)polymorphism and templates. Sorry, but that is not possible.
Templates operate on types at compile time, also called static types. The static type of message is Message, while its dynamic type might be either Message1 or Message2. Templates don't know anything about dynamic types and they can't operate on them. Go with either runtime polymorphism or compile-time polymorphism, sometimes also called static polymorphism.
The runtime polymorphism approach is the visitor pattern, with double dispatch. Here is an example of compile-time polymorphism, using the CRTP idiom:
template<class TDerived>
class Message{};
class Message1 : public Message<Message1>{};
class Message2 : public Message<Message2>{};
template<class TMessage>
class MessageWithData : public TMessage { public: int x, y; };
class Handler{
public:
template<class TMessage>
void process(Message<TMessage> const& m, int x, int y){
MessageWithData<TMessage> mwd;
mwd.x = 42;
mwd.y = 1337;
}
};
You have
void process(const Message& message, int x, int y)
{
// HERE
messageWithData.dispatch(...)
}
At HERE, you want to create either a MessageWithData<Message1> or a MessageWithData<Message2>, depending on whether message is an instance of Message1 or Message1.
But you cannot do that, because the class template MessageWithData<T> needs to know at compile time what T should be, but that type is not available at that point in the code until runtime by dispatching into message.
As has been mentioned, it is not possible to build your template as is.
I do not see any issue with passing additional parameters, though I would perhaps pack them into a single structure, for ease of manipulation.
Certainly I find it more idiomatic to use a supplementary Data parameter, rather than extending a class hierarchy to shoehorn all this into a pattern.
It is an anti-pattern to try to make a design fit a pattern. The proper way is to adapt the pattern so that it fits the design.
That being said...
There are several alternatives to your solution. Inheritance seems weird, but without the whole design at hand it may be your best bet.
It has been mentioned already that you cannot freely mix compile-time and run-time polymorphisms. I usually use Shims to circumvent the issue:
class Message {};
template <typename T> class MessageShim<T>: public Message {};
class Message1: public MessageShim<Message1> {};
The scheme is simple and allow you to benefit from the best of both worlds:
Message being non-template mean that you can apply traditional OO strategies
MessageShim<T> being template mean that you can apply traditional Generic Programming strategies
Once done, you should be able to get what you want, for better or worse.
As Xeo says, you probably shouldn't do this in this particular case - better design alternatives exist. That said, you can do it with RTTI, but it's generally frowned upon because your process() becomes a centralised maintenance point that needs to be updated as new derived classes are added. That's easily overlooked and prone to run-time errors.
If you must persue this for some reason, then at least generalise the facility so a single function uses RTTI-based runtime type determination to invoke arbitrary behaviour, as in:
#include <iostream>
#include <stdexcept>
struct Base
{
virtual ~Base() { }
template <class Op>
void for_rt_type(Op& op);
};
struct Derived1 : Base
{
void f() { std::cout << "Derived1::f()\n"; }
};
struct Derived2 : Base
{
void f() { std::cout << "Derived2::f()\n"; }
};
template <class Op>
void Base::for_rt_type(Op& op)
{
if (Derived1* p = dynamic_cast<Derived1*>(this))
op(p);
else if (Derived2* p = dynamic_cast<Derived2*>(this))
op(p);
else
throw std::runtime_error("unmatched dynamic type");
}
struct Op
{
template <typename T>
void operator()(T* p)
{
p->f();
}
};
int main()
{
Derived1 d1;
Derived2 d2;
Base* p1 = &d1;
Base* p2 = &d2;
Op op;
p1->for_rt_type(op);
p2->for_rt_type(op);
}
In the code above, you can substitute your own Op and have the same runtime-to-compiletime handover take place. It may or may not help to think of this as a factory method in reverse :-}.
As discussed, for_rt_type has to be updated for each derived type: particularly painful if one team "owns" the base class and other teams write derived classes. As with a lot of slightly hacky things, it's more practical and maintainable in support of private implementation rather than as an API feature of a low-level enterprise library. Wanting to use this is still typically a sign of bad design elsewhere, but not always: occasionally there are algorithms (Ops) that benefit enormously:
compile-time optimisations, dead code removal etc.
derived types only need same semantics, but details can vary
e.g. Derived1::value_type is int, Derived2::value_type is double - allows algorithms for each to be efficient and use appropriate rounding etc.. Similarly for different container types where only a shared API is exercised.
you can use template metaprogramming, SFINAE etc. to customise the behaviours in a derived-type specific way
Personally, I think knowledge of and ability to apply this technique (however rarely) is an important part of mastering polymorphism.