Hi is there a container where a key is a typename and value is an object/instance in boost or std???
What I want to achieve is I have a object pool for each data type and when I want to construct that object I want to just fetch by Key. I already have working code but I would be happier if i used something more standard.
Currently I have a code like this:
template<size_t index, size_t counter, typename T0, typename ...T>
struct PoolBuilderInternal
{
typedef typename boost::mpl::insert<
typename PoolBuilderInternal<index - 1, counter + 1, T...>::m
, boost::mpl::pair<T0, std::integral_constant<size_t, counter> > >::type m;
};
template<size_t counter, typename T0, typename ...T>
struct PoolBuilderInternal<1, counter, T0, T...>
{
typedef typename boost::mpl::map<boost::mpl::pair<T0, std::integral_constant<size_t, counter> > > m;
};
template<typename ...T>
struct Pools
{
std::tuple<
boost::object_pool<T>...> m_pools;
typedef typename PoolBuilderInternal<sizeof...(T), 0, T...>::m poolType;
template<typename T>
boost::object_pool<T>& GetPool()
{
return std::get< boost::mpl::at<poolType, T>::type::value>(m_pools);
}
};
Pools<int, std::string, int64_t> m_pools;
m_pools.Get<int>();
EDIT: What I want is a COMPILE-TIME map. You can imagine a std::tuple<> but some that wouldnt not be accessed by index std::get<0,1,2>... but rather by a key (?std::tuple_map)
If types in the pool are unique use c++ 14 std::get< T >(std::tuple(s))
#include <iostream>
#include <string>
#include <tuple>
struct A
{
int value = 17;
};
int main()
{
auto t = std::make_tuple(1, std::string{"Foo"}, 3.14, A{});
std::cout << "(" << std::get<int>(t) << ", "
<< std::get<std::string>(t)
<< ", " << std::get<double>(t)
<< ", " << std::get<A>(t).value << ")\n";
}
If I understand this question right (and I'm not sure I do), what you really want is some kind of class factory, and that, in various forms, is a well-known design pattern because it allows users of the factory to construct objects whose constructors (and indeed types, quite often, when a class hierarchy is involved) are unknown or off-limits to them.
On that basis, I humbly offer you the following proof-of-concept code. Please note that I threw this together in rather a hurry and it's probably not optimal. I'm sure more is possible, including passing parameters to the relevant constructors to make_string() and make_foo() from the call site (e.g. factory [t_string] ("My string"). I'll look into that when I have time, if you show any interest in this post.
OK, so here's your class factory. You should be able to apply it to any types, including boost types. As coded, any parameters that need to be passed to the object in question are currently defined when the factory function (e.g. make_string) is added to the map (which is probably not ideal). These factory functions also could / should be lambdas. Again, I'll add that in later.
#include <functional>
#include <unordered_map>
#include <variant>
#include <iostream>
struct Foo
{
Foo (int x) : x (x) { }
int x;
};
enum ObjectType { t_string, t_foo }; // ...
using all_possible_types = std::variant <std::string, Foo>; // ...
static all_possible_types make_string (const std::string& s)
{
std::cout << "make_string " << s << "\n";
return all_possible_types (std::string (s));
}
static all_possible_types make_foo (int x)
{
std::cout << "make_foo " << x << "\n";
return all_possible_types (Foo (x));
}
// ...
int main()
{
std::unordered_map <ObjectType, std::function <all_possible_types ()>> factory;
factory.insert ({t_string, std::bind (make_string, "Initial string value")});
factory.insert ({t_foo, std::bind (make_foo, 42)});
// ...
all_possible_types variant_string = factory [t_string] ();
std::cout << std::get <std::string> (variant_string) << "\n\n";
all_possible_types variant_foo = factory [t_foo] ();
std::cout << std::get <Foo> (variant_foo).x << "\n";
}
Output:
make_string Initial string value
Initial string value
make_foo 42
42
Live demo.
As I say, this doesn't look like much now but I will improve it later. In the meantime, I suggest you take a look at it to get your head around what I'm doing here.
Related
I am trying to write a vector wrapper (indexed_vec) which stores objects of type ValueType but other datastructures (vectors of other types) refer to these by index (because iterators are clearly not stable).
So when objects of ValueType are deleted in indexed_vec, some housekeeping has to be done to keep the indeces in the other other datastructures up to date.
Therefore indexed_vec also stores 2 lambda's which are effectively "subscribers" (Observer Pattern) to index changes.
The code below works, as desired, but the syntax for constructing the instance of indexed_vec seems clumsy.
Are there better alternatives? I investigated deduction guides, but that doesn't work apparently.
A factory function?
(NOTE: the wrappers exposing of the inner vector as a public members will not stay like that, it's just to reduce the code here)
#include <cstddef>
#include <iostream>
#include <vector>
template <typename ValueType, typename DeleteIndexCBType, typename ChangeIndexCBType>
struct indexed_vec {
indexed_vec(DeleteIndexCBType& dcb_, ChangeIndexCBType& ccb_) : dcb(dcb_), ccb(ccb_) {}
DeleteIndexCBType dcb;
ChangeIndexCBType ccb;
std::vector<ValueType> v;
std::size_t erase(std::size_t index_to_erase) {
// TODO handle empty vector
v[index_to_erase] = v.back();
v.pop_back();
dcb(index_to_erase);
ccb(v.size(), index_to_erase); // NOTE v.size() is NOW one off the end, but that's accurate
return 1;
}
};
template <typename T>
void print(const std::vector<T>& v) {
for (auto& e: v) std::cout << e << " ";
std::cout << '\n';
}
int main() {
std::string context = "captured context";
auto delete_subscriber = [&context](std::size_t idx) {
std::cout << "deleter: " << context << ": " << idx << "\n";
};
auto change_subscriber = [&context](std::size_t old_idx, std::size_t new_idx) {
std::cout << "updater: " << context << ": " << old_idx << " => " << new_idx << "\n";
};
// this seems clumsy?
indexed_vec<std::size_t, decltype(delete_subscriber), decltype(change_subscriber)> v1(
delete_subscriber, change_subscriber);
v1.v.reserve(10);
for (std::size_t v = 10; v != 20; ++v) v1.v.push_back(v);
print(v1.v);
v1.erase(3);
print(v1.v);
}
One easy easy way to simplify the syntax is to wrap the verbose code in a factory function like
template <typename ValueType, typename DeleteIndexCBType, typename ChangeIndexCBType>
auto make_index_vector(const DeleteIndexCBType& dcb_, const ChangeIndexCBType& ccb_)
{
return indexed_vec<ValueType, DeleteIndexCBType, ChangeIndexCBType>(dcb_, ccb_);
}
Using that allows you to declare v1 like
auto v1 = make_index_vector<std::size_t>(delete_subscriber, change_subscriber);
Since you can't supply only one template parameter out of three, a normal deduction guide won't work, but you could package ValueType in a tag.
template <class T> struct ValueTag {};
template <class ValueType, class DeleteIndexCBType, class ChangeIndexCBType>
struct indexed_vec {
// added constructor for tag:
indexed_vec(ValueTag<ValueType>, DeleteIndexCBType& dcb_,
ChangeIndexCBType& ccb_) :
dcb(dcb_), ccb(ccb_) {}
//...
Deduction guide:
template<class ValueType, class DeleteIndexCBType, class ChangeIndexCBType>
indexed_vec(ValueTag<ValueType>, DeleteIndexCBType, ChangeIndexCBType) ->
indexed_vec<ValueType, DeleteIndexCBType, ChangeIndexCBType>;
Usage:
indexed_vec v1(ValueTag<size_t>{}, delete_subscriber, change_subscriber);
I am looking for a class that is like std::variant that holds all types instead of one of the types.
So I would like to be able to write:
std::all_variant<int, double> av{1, 3.14159};
int i = std::get<int>(av); // i should be 1.
double d = std::get<double>(av); // d should be 3.14159
This is basically a tuple but guarantees that each type appears only once so you can do std::get<Type> instead of std::get<Index>.
For context I want to be able to write the following code (so if there is a better way of doing that I would appreciate to know):
std::all_variant<int, double> av{1, 3.14159};
template <typename T> // T must be either int or double.
void MyFunc(std::all_variant<int, double> av) {
std::cout << std::get<T>(av);
}
int main() {
MyFunc<int>(av); // Should print 1.
MyFunc<double>(av); // Should print 3.14159.
MyFunc<std::string>(av); // Error! av doesn't have std::string variant.
}
I'm not sure what this would be called so I'm not sure if this is in the standard library. I guess it wouldn't be to hard to write one but I don't want to reinvent the wheel.
I am looking for a class that is like std::variant that holds all types instead of one of the types.
What you are looking for is called std::tuple
std::tuple<int,double> mytup( 1, 2.0 );
std::cout << std::get<int>( mytup ) << "\n"; // prints 1
std::cout << std::get<double>( mytup ) << "\n"; // prints 2
std::cout << std::get<std::string>( mytup ) << "\n"; // compiler error
Live example
As for single type appearance requirement you would get compilation error when you try to use std::get<type> instead of index with std::tuple with duplicated types. (thanks #max66)
In addition to Slava's answer, you can enforce type-uniqueness in a tuple using for example something like is_unique from this post:
#include <tuple>
#include <type_traits>
// From https://stackoverflow.com/a/47511516
template <typename...>
inline constexpr auto is_unique = std::true_type{};
template <typename T, typename... Rest>
inline constexpr auto is_unique<T, Rest...> = std::bool_constant<
(!std::is_same_v<T, Rest> && ...) && is_unique<Rest...>
>{};
// Tuple that only accept unique type parameters
template<typename... Ts>
using uniq_tuple = typename std::enable_if<is_unique<Ts...>, std::tuple<Ts...>>::type;
int main()
{
// Compiles
uniq_tuple<int, float> t1;
// Fails
uniq_tuple<int, float, int> t2;
return 0;
}
What i need is to create a class that can hold boost::multi_array of same type but with different dimentions
assume there are one or more such arrays of Double
boost::multi_array<double, 2> array_2d; //2D array
boost::multi_array<double, 3> array_3d; //4D array
boost::multi_array<double, 4> array_4d; //5D array
etc...
i need a container class that can hold all of the above types that is able to deference the correct type later when needed
something like
GenericArray<double> arr;
arr.IsEmpty() // check if it has valid ref
arr.assign(array_2d); //set reference to
then get back the reference to the array using some sort of template logic
try{
boost::multi_array<double, 2>& array_2d_ref = arr.get<2>
//OR
boost::multi_array<double, 2>& array_2d_ref = arr.get<multi_array<double, 2>>
// First one look cleaner tho
}catch (ArrayDimentinalityMismatch e){
}
In Same code block
arr.assign(array_3d);
try{
boost::multi_array<double, 2>& array_3d_ref=arr.get<multi_array<double, 3>>
}catch (ArrayDimentinalityMismatch e){
}
Is This possible using templates?
Firstly, I think you may want to evaluate your design. Like with functors, it's rarely required to code semi-rigid type wrappers around your generic type arguments.
However, if you do find you have a need for this, here's a solution that uses boost::variant:
template <typename T>
struct GenericArray
{
template <size_t N> using array_t = boost::multi_array<T, N>;
template <typename Rhs> GenericArray& operator=(Rhs&& rhs) {
_storage = std::forward<Rhs>(rhs);
return *this;
}
template <size_t N> array_t<N> & get() { return boost::get<array_t<N> >(_storage); }
template <size_t N> array_t<N> const& get() const { return boost::get<array_t<N> >(_storage); }
private:
typename detail::make_generic_array_storage<T>::type _storage;
};
The get<> member function throws a boost::bad_get exception if you get the dimension wrong at runtime.
Now, the trick is, of course, how _storage is implemented. I generate a variant over a list of array dimensions using a bit of Boost MPL magic:
namespace detail {
namespace mpl = boost::mpl;
template <typename T, size_t Mindim = 1, size_t Maxdim = 5>
struct make_generic_array_storage
{
template <size_t N> using array_t = boost::multi_array<T, N>;
template<typename N> struct to_array_f { typedef array_t<N::value> type; };
using list = typename mpl::transform<
mpl::range_c<size_t, Mindim, Maxdim>,
to_array_f<mpl::_1>,
mpl::back_inserter<mpl::vector<> >
>::type;
using type = typename boost::make_variant_over<list>::type;
};
}
Nothing overly complicated, if you look at it from a high level :)
Next up: demo! See it Live On Coliru
GenericArray<double> arr;
arr = array_3d;
try { auto& ref3 = arr.get<3>(); }
catch (boost::bad_get const& e) { std::cout << "L:" << __LINE__ << " " << e.what() << "\n"; }
try { auto& ref2 = arr.get<2>(); } // this fails
catch (boost::bad_get const& e) { std::cout << "L:" << __LINE__ << " " << e.what() << "\n"; }
arr = array_2d;
try { auto& ref2 = arr.get<2>(); } // this succeeds
catch (boost::bad_get const& e) { std::cout << "L:" << __LINE__ << " " << e.what() << "\n"; }
std::cout << "Done";
Prints:
L:58 boost::bad_get: failed value get using boost::get
Done
as expected.
Bonus: To implement more array-like operations over the variant storage, have a look here:
Generating an interface without virtual functions?
How to create a interface for serialization in Boost Serialization?
which touch on this topic
std::bind is sometimes described as "partial application". Any reasons why when all parameters of a function are bound, the function itself isn't applied?
For example, the following code prints nothing.
#include <functional>
#include <iostream>
using namespace std;
using namespace std::placeholders;
void f(int a,string b) {cout << a << b << endl;};
int main() {
bind(bind(f,1,_1),"Hi!");
return 0;
}
Is there a way to write a bind variant that can apply the function when all parameters are fixed?
--Update--
I understand from the responses now that std::bind is not exactly partial application. So, on the second part of the question, how can I write something like std::bind but does partial application.
I know bind(bind(f,1,_1),"Hi!")() will call the final 0-ary function and return the result value (printing 1Hi in the example). Is it possible to do template programming to call the function call operator () in the terminal case of bind?
In other words, is it possible to write a function bind1:
template< class R, class F, class... Args >
bind1( F f, Args... args )
, such that when std::is_placeholder<T>::value == 0 for each member of args,
bind1() can, in addition to what std::bind() does, call the operator()?
A function with no arguments is just a value in Haskell. You don't call it, you just use it. Since there are no side effects, there is no observable difference.
In OCaml there are simply no parameter-less functions, to get something like that you need to add a dummy unit argument.
Not so in C++. C++, unlike Haskell and OCaml, maintains clear difference between f and f(). bind gives you the former because you can always turn it into the latter by adding (). You can write your own wrapper for bind that does just that quite easily. Going the other way around would be a tad more difficult.
Here's a possible implementation of such wrapper:
#include <functional>
#include <utility>
#include <iostream>
template <typename T>
struct is_noargs_callable {
private:
typedef char(&yes)[1];
typedef char(&no)[2];
template<typename U>
static yes test(decltype((std::declval<U>())())*);
template<typename>
static no test(...);
public:
static const bool value = sizeof(test<T>(0)) == sizeof(yes);
};
template <typename T>
struct is_noargs_callable<T()> {
static const bool value = true;
};
template <typename T>
struct is_noargs_callable<T(...)> {
static const bool value = true;
};
template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<is_noargs_callable<T>::value, decltype(t())>::type
{
return t();
}
template <typename T>
auto call_me_if_you_can(T t) -> typename std::enable_if<!is_noargs_callable<T>::value, T>::type
{
return t;
}
template <typename... Args>
auto apply(Args&&... args) -> decltype(call_me_if_you_can(std::bind(args...))) {
return call_me_if_you_can(std::bind(args...));
}
// testing
void foo(int a, int b, int c) { std::cout << "foo(" << a << "," << b << "," << c << ")"; }
int main ()
{
using namespace std::placeholders;
std::cout << "zero : " ; apply(foo, _1, _2, _3); std::cout << " : " ; apply(foo, _1, _2, _3)(1,2,3); std::cout << std::endl;
std::cout << "one : " ; apply(foo, 1, _1, _2); std::cout << " : " ; apply(foo, 1, _1, _2)(2,3); std::cout << std::endl;
std::cout << "two : " ; apply(foo, 1, 2, _1); std::cout << " : " ; apply(foo, 1, 2, _1)(3); std::cout << std::endl;
std::cout << "three: " ; apply(foo, 1, 2, 3); std::cout << " : "; /* nothing to test here */ std::cout << std::endl;
}
However, killing the difference between f and f() just in this one place does not IMHO contribute to the overall consistency of C++ programming. If you don't like the distinction, kill it everywhere (or just use you a Haskell for great good).
No sources for this, just my opinion.
The reason that wasn't done is because there is no reason to do it. If you know all of the input to the function, just call it.
And if you were doing something with templates that resulted in this, you would need to write all of the code consistently anyway. A special case here would only require a special case somewhere else.
I would like to use a boost.variant<T0,T1,T2> as a parameter to a template 'Visitor' class which would provide visitor operators as required by the boost.variant visitor mechanism, in this case all returning void i.e.,
void operator()(T0 value);
void operator()(T1 value);
void operator()(T2 value);
The template would also have for each of the types T0... in the variant a corresponding virtual function which by default does nothing. The user is able inherit from the template class and redefine only those virtual functions which he is interested in. This is something akin to the well-known 'Template Method' pattern.
The only solution I have been able to come up with is by wrapping both the boost::variant and the associated visitor in a single template, and accessing them via typedefs. This works okay, however it feels a little clunky. Here's the code:
#include "boost/variant.hpp"
//create specializations of VariantWrapper for different numbers of variants -
//just show a template for a variant with three types here.
//variadic template parameter list would be even better!
template<typename T0, typename T1, typename T2>
struct VariantWrapper
{
//the type for the variant
typedef boost::variant<T0,T1,T2> VariantType;
//The visitor class for this variant
struct Visitor : public boost::static_visitor<>
{
void operator()(T0 value)
{
Process(value);
}
void operator()(T1 value)
{
Process(value);
}
void operator()(T2 value)
{
Process(value);
}
virtual void Process(T0 val){/*do nothing */}
virtual void Process(T1 val){/*do nothing */}
virtual void Process(T2 val){/*do nothing */}
protected:
Visitor(){}
};
typedef Visitor VisitorType;
private:
VariantWrapper(){}
};
The class is then used as follows:
typedef VariantWapper<bool,int,double> VariantWrapperType;
typedef VariantWrapperType::VariantType VariantType;
typedef VariantWrapperType::VisitorType VisitorType;
struct Visitor : public VisitorType
{
void Process(bool val){/*do something*/}
void Process(int val){/*do something*/}
/* this class is not interested in the double value */
};
VariantType data(true);
apply_visitor(Visitor(),data);
As I say, this seems to work okay but I would prefer it if I didn't have to create a special wrapper class to tie the variant and the visitor together. I would prefer to be able just to use a boost.variant directly to instantiate the template visitor class. I've had a look at using type parameters, non-type parameters and template template parameters but nothing seems to suggest itself. Is what I am trying to do not possible? I may be missing something, and would appreciate it if anyone has any input on this.
The code with Boost Variant and virtual dispatching is a little fishy. Especially taking into account that you know what are you interested in processing during the compile-time and there is absolutely no need in creating a virtual table at run-time in order to achieve your goals.
I would recommend you use partial template specialization. Thus, have a default template method that can accept any type in the variant and will do nothing. For those types you are interested in, just specialize template.
Here is an example. We have three types - Foo, Bar and War. We are interested only in the last two types and have a specialization for them. So Foo is being ignored.
#include <iostream>
#include <boost/variant.hpp>
using namespace std;
using namespace boost;
struct Foo {};
struct Bar {};
struct War {};
typedef variant<Foo, Bar, War> Guess;
struct Guesstimator : public boost::static_visitor<void>
{
template <typename T>
void operator () (T) const
{
}
};
template <>
inline void
Guesstimator::operator () <Bar> (Bar) const
{
cout << "Let's go to a pub!" << endl;
}
template <>
inline void
Guesstimator::operator () <War> (War) const
{
cout << "Make love, not war!" << endl;
}
Here is a simple example of the usage:
int
main ()
{
Guess monday;
apply_visitor (Guesstimator (), monday);
War war;
Guess ww2 (war);
apply_visitor (Guesstimator (), ww2);
Bar irishPub;
Guess friday (irishPub);
apply_visitor (Guesstimator (), friday);
}
The output of this program will be:
Make love, not war!
Let's go to a pub!
Here is another solution. We create a default visitor ignoring everything, except what you have specified in a type list. It is not that convenient because you have to specify a list of types twice - once in a type list and then in each processing method (operator). Plus, the generic template, in fact, will be inheriting your visitor. But nevertheless, here we go:
#include <cstddef>
#include <iostream>
#include <boost/variant.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/utility/enable_if.hpp>
// Generic visitor that does magical dispatching of
// types and delegates passes down to your visitor only
// those types specified in a type list.
template <typename Visitor, typename TypeList>
struct picky_visitor :
public boost::static_visitor<void>,
public Visitor
{
template <typename T>
inline void
operator () (T v, typename boost::enable_if< typename boost::mpl::contains< TypeList, T >::type >::type *dummy = NULL) const
{
Visitor::operator () (v);
}
template <typename T>
inline void
operator () (T v, typename boost::disable_if<typename boost::mpl::contains< TypeList, T >::type >::type *dummy = NULL) const
{
}
};
// Usage example:
struct nil {};
typedef boost::variant<nil, char, int, double> sql_field;
struct example_visitor
{
typedef picky_visitor< example_visitor, boost::mpl::vector<char, int> > value_type;
inline void operator () (char v) const
{
std::cout << "character detected" << std::endl;
}
inline void operator () (int v) const
{
std::cout << "integer detected" << std::endl;
}
};
int
main ()
{
example_visitor::value_type visitor;
sql_field nilField;
sql_field charField ('X');
sql_field intField (1986);
sql_field doubleField (19.86);
boost::apply_visitor (visitor, nilField);
boost::apply_visitor (visitor, charField);
boost::apply_visitor (visitor, intField);
boost::apply_visitor (visitor, doubleField);
}
As time passes new and interesting libraries develop. This question is old, but since then there is a solution that to me personally is far more superior to the ones that have been given so far.
The excellent Mach7 library which allows unprecedented matching (and therefore visiting) capabilities. It is written by Yuriy Solodkyy, Gabriel Dos Reis and Bjarne Stroustrup himself. For the ones stumbling on this question, here is an example taken from the README:
void print(const boost::variant<double,float,int>& v)
{
var<double> d; var<float> f; var<int> n;
Match(v)
{
Case(C<double>(d)) cout << "double " << d << endl; break;
Case(C<float> (f)) cout << "float " << f << endl; break;
Case(C<int> (n)) cout << "int " << n << endl; break;
}
EndMatch
}
I am working with it now and so far it is a real pleasure to use.
Tom, I believe that your question makes much sense in a particular context. Say that you want to store visitors of multiple types in a vector, but you can't because they are all of different types. You have a few choices: use variant again to store visitors, use boost.any, or use virtual functions. I think that virtual functions are an elegant solution here, but certainly not the only one.
Here is how it goes.
First, let's use some variant; bool, int, and float will do.
typedef boost::variant<bool, int, float> variant_type;
Then comes the base class, more or less as you had it.
template
struct Visitor : public boost::static_visitor<>
{
void operator()(T0 value)
{
Process(value);
}
void operator()(T1 value)
{
Process(value);
}
void operator()(T2 value)
{
Process(value);
}
virtual void Process(T0 val){ std::cout << "I am Visitor at T0" << std::endl; }
virtual void Process(T1 val){ std::cout << "I am Visitor at T1" << std::endl; }
virtual void Process(T2 val){ std::cout << "I am Visitor at T2" << std::endl; }
protected:
Visitor(){}
};
Next, we have two specific variants.
template
struct Visitor1 : public Visitor
{
void Process(T0 val){ std::cout << "I am Visitor1 at T0" << std::endl; }
void Process(T2 val){ std::cout << "I am Visitor1 at T2" << std::endl; }
};
template
struct Visitor2 : public Visitor
{
void Process(T1 val){ std::cout << "I am Visitor2 at T1" << std::endl; }
void Process(T2 val){ std::cout << "I am Visitor2 at T2" << std::endl; }
};
Finally, we can make a single vector of different variants:
int main() {
variant_type data(1.0f);
std::vector*> v;
v.push_back(new Visitor1());
v.push_back(new Visitor2());
apply_visitor(*v[0],data);
apply_visitor(*v[1],data);
data = true;
apply_visitor(*v[0],data);
apply_visitor(*v[1],data);
return 0;
}
And here is the output:
I am Visitor1 at T2
I am Visitor2 at T2
I am Visitor1 at T0
I am Visitor at T0
If for some reason I needed to have different variants in one container, I would surely consider this solution. I would also think how much worse/better would it be to actually stick the visitors into another variant. The nice thing about using inheritance is that it is extensible post factum: you can always inherit from a class, but once a variant is set, you can't change it without actually touching the existing code.