My problem is the following. I am learning C++ by writing a graph library and want to make use of as much generic programming techniques as possible; hence, answering my question through "use BOOST" will not help me; in fact, I tried looking through BOOST's code for an answer to my question, but it was a humbling experience, since I can't even figure out where certain functions are defined; just way too high level of C++ for learning from it at my level.
That said, my library is templated in the following way:
class edge { ... };
template <class edge_T>
class node { ... };
template <class edge_T, class node_T>
class graph { ... };
and I am creating more complex graphs by using classes derived from edge or node, so a weighted edge class would be simply
template <class T>
class weighted_edge : public edge {
public:
T weight;
...
};
The problem now is that I want to implement an algorithm on this structure that computes the shortest distance between two vertices. I could easily write two of these, one for weighted edges and one for unweighted, but the change is tiny: one would access a member field of weighted_edge (or derived classes) and the other would assume unitary weight.
Is there a way of doing this, so that I can have just one piece of code for both cases?
One solution is to use a member function edge::get_weight() that would return the weight (or '1' in unweighted case), but that would force me to use a specific weight type for edge class that is unweighted, so it smells funny. I mean, the template would need to be
template <class T>
class edge {
public:
...
virtual T get_weight(void) { return T(1); }
}
which is not exactly user-friendly, or at least confusing, since you don't expect that there should be any weights involved.
BGL uses a get() function to obtain the weight; I could write a function that returns 1 or the weight depending on the edge_T, but my concern is what happens when one derives from edge or weighted_edge? If one writes:
template <class T>
inline T get_weight(edge & e) { return T(1); }
template <class T>
inline T get_weight(weighted_edge & e) { return T(e.weight); }
what would happen if one passed a derived class? Is there a C++ mechanism that would select the 'closer' base class out of these two?
Thanks for the response, sehe; I figured out the optimal solution for my problem. It is to write two functions,
template <class T>
inline T get_weight(edge const & e)
{ return T(1); }
template <class T>
inline T get_weight(weighted_edge const & e)
{ return T(e.weight); }
This way, when I write a shortest-path algorithm it can ask for the weight of either of these two classes or any derived ones, which is important to me because I might want to add properties to the base edge classes later on (like colors, etc.). Hence, when I write
class my_edge : public edge { ... };
my_edge e;
and use get_weight(e) I will get the behavior for the unweighted edge. Templating on the edge type would not help here, because it would not be able to use the prescribed behavior on all classes descending from edge, and distinguishing that from the behavior for weighted_edge.
Up front: I assume you have thought of making getWeight() a virtual method in the base edge class (and make the default implementation return 1). I'm aware of the limitations in flexibility of this approach, just wanted to check.
Because I didn't understand the purpose of your return type templae, I assumed that you wanted to deduce the return type, which you can do using my solution.
The usual way to make get_weight select the right implementation is to use template specialization (note that the code you show specializes by return type; by definition this type would never be deduced by the compiler):
namespace detail
{
template <class Edge> struct get_weight_impl;
template <> struct get_weight_impl<edge>
{
typedef typename result_type int;
result_type operator()(const edge& e) const
{ return result_type(1); }
};
template <> struct get_weight_impl<weighted_edge>
{
typedef typename result_type int;
result_type operator()(const weighted_edge& e) const
{ return result_type(e.weight); }
};
}
Update 1 You could employ result_of<edge::weight> (boost/TR1) or decltype(edge::weight) (C++0x) to avoid hardcoding the result_type typedefs. This would be true induction.
Update 2 To get the overload for weighted_edge const& to 'service' derived edge types as well apply a little bit of type_trait magic:
http://ideone.com/AqmsL
struct edge {};
struct weighted_edge : edge { virtual double get_weight() const { return 3.14; } };
struct derived_edge : weighted_edge { virtual double get_weight() const { return 42; } };
template <typename E, bool is_weighted>
struct edge_weight_impl;
template <typename E>
struct edge_weight_impl<E, false>
{
typedef int result_type;
int operator()(const E& e) const { return 1; }
};
template <typename E>
struct edge_weight_impl<E, true>
{
// typedef decltype(E().weight()) result_type; // c++0x
typedef double result_type;
result_type operator()(const E& e) const
{
return e.get_weight();
}
};
template <typename E>
typename edge_weight_impl<E, boost::is_base_of<weighted_edge, E>::value>::result_type
get_weight(const E& e)
{
return edge_weight_impl<E, boost::is_base_of<weighted_edge, E>::value>()(e);
}
int main()
{
edge e;
weighted_edge we;
derived_edge de;
std::cout << "--- static polymorphism" << std::endl;
std::cout << "edge:\t" << get_weight(e) << std::endl;
std::cout << "weighted_edge:\t" << get_weight(we) << std::endl;
std::cout << "derived_edge:\t" << get_weight(de) << std::endl;
// use some additional enable_if to get rid of this:
std::cout << "bogus:\t" << get_weight("bogus") << std::endl;
std::cout << "\n--- runtime polymorphism" << std::endl;
edge* ep = &e;
std::cout << "edge:\t" << get_weight(*ep) << std::endl;
weighted_edge* wep = &we;
std::cout << "weighted_edge:\t" << get_weight(*wep) << std::endl;
wep = &de;
std::cout << "bogus:\t" << get_weight(*wep) << std::endl;
}
Related
I have a class and need to validate that it's function calls are being called w/ the right parameters. The function signature is always the same (sans 1 argument type). So, naturally I went for a templated approach. So generally the validation policy would have a template parameter per data type it could handle:
using P = Policy<int, double, UserDefined>
Or something of that ilk.
I got it to compile, but the caveat is that if double and int (or anything a double can convert to actually) are both template parameters, the double will be implicitly converted.
The policy looks like this:
template <typename... T>
class BasicValidationPolicy { };
template <>
class BasicValidationPolicy<>
{
public:
void RegisterSetHandler();
};
template <typename T, typename... Rest>
class BasicValidationPolicy<T, Rest...> : public BasicValidationPolicy<Rest...>
{
public:
using SetHandler = std::function<void(int, T)>;
void RegisterSetHandler(const SetHandler& handler)
{
m_setHandler = handler;
}
void Set(int n, const T& val) {
if (m_setHandler) {
m_setHandler(n, val);
}
}
private:
SetHandler m_setHandler{nullptr};
};
The class that uses it...
template <typename ValidatorPolicy>
class MyClass : public ValidatorPolicy {
public:
void OnSetInt(int n, int64_t v)
{
ValidatorPolicy::Set(n, v);
}
void OnSetDouble(int n, double d)
{
ValidatorPolicy::Set(n, d);
}
};
Usage:
int main()
{
using Policy = BasicValidationPolicy<int64_t, double>; // doesn't work
MyClass<Policy> m;
m.Policy::RegisterSetHandler([](int i, double value) {
// by this point value is an int64_t
std::cout << "Got double " << i << ", " << value << "\n";
});
double d{35.2135};
m.OnSetDouble(1, d);
}
To boot, doing this does work
using Policy = BasicValidationPolicy<double, int64_t>;
So I guess I'm missing something about the template deduction. Looks like it tries to match double against std::int64_t says "meh, good enough", and moves on. Nice to know a way around it (kind of) but that looks like it would be very tricky to maintain.
It's complicated...
First of all: you have a recursive template class, BasicValidationPolicy, where you define two methods and you want that all methods, for all recursion steps of the class, are available.
Unfortunately, the definition of the methods in the derived classes hide the method in base classes.
To un-hide the inherited methods, you have to explicitly add a pair of using
using BasicValidationPolicy<Rest...>::Set;
using BasicValidationPolicy<Rest...>::RegisterSetHandler;
At this point, the code doesn't compile because you need a Set() and a RegisterSetHandler() in the ground case class. You have declared a dummy RegisterSetHandler() but not a dummy Set(). You have to add one, so the ground case become
template <>
class BasicValidationPolicy<>
{
public:
void RegisterSetHandler();
void Set();
};
Now your MyClass<Policy> object expose two RegisterSetHandler() methods (before only one): one receiving a std::function<void(int, std::int64_t)>, the other (before hidden) receiving a std::function<void(int, double)>.
But when you pass a lambda, you have a chicken-and-egg problem: the lambda can be converted to a std::function but isn't a std::function. So can't be used to deduce the template parameters of std::function because the types are to be known before to deduce them.
A possible solution is impose a lambda/std::function conversion in the call
// ..........................VVVVVVVVVVVVVV
m.Policy::RegisterSetHandler(std::function{[](int i, double value) {
// by this point value is an int64_t
std::cout << "Got double " << i << ", " << value << "\n";
}});
// ...........................^
using also the template deduction guides introduced in C++17.
So your code become
#include <iostream>
#include <functional>
template <typename... T>
class BasicValidationPolicy { };
template <>
class BasicValidationPolicy<>
{
public:
void RegisterSetHandler();
void Set();
};
template <typename T, typename... Rest>
class BasicValidationPolicy<T, Rest...> : public BasicValidationPolicy<Rest...>
{
public:
using SetHandler = std::function<void(int, T)>;
using BasicValidationPolicy<Rest...>::Set;
using BasicValidationPolicy<Rest...>::RegisterSetHandler;
void RegisterSetHandler(const SetHandler& handler)
{
m_setHandler = handler;
}
void Set(int n, const T& val) {
if (m_setHandler) {
m_setHandler(n, val);
}
}
private:
SetHandler m_setHandler{nullptr};
};
template <typename ValidatorPolicy>
class MyClass : public ValidatorPolicy {
public:
void OnSetInt(int n, int64_t v)
{
ValidatorPolicy::Set(n, v);
}
void OnSetDouble(int n, double d)
{
ValidatorPolicy::Set(n, d);
}
};
int main ()
{
using Policy = BasicValidationPolicy<int64_t, double>; // doesn't work
MyClass<Policy> m;
m.Policy::RegisterSetHandler(std::function{[](int i, double value) {
std::cout << "Got double " << i << ", " << value << "\n";
}});
double d{35.2135};
m.OnSetDouble(1, d);
}
There's a small alternative to the recursive definition that might be easier to work with...
template<typename T>
class ValidationPolicy {
// Set/Register/etc
};
template <typename... Ts>
class BasicValidationPolicy : public ValidationPolicy<Ts>... {
public:
using ValidationPolicy<Ts>::Set...;
using ValidationPolicy<Ts>::RegisterSetHandler...;
};
This can have some impacts on compile time and other aspects of development, though most likely relatively minor. For instance, if you have dozens of classes used in hundreds of different policy combinations in your app, the recursive definition will lead to many more distinct types and larger binaries to support that. For example, in the recursive definition BasicValidationPolicy<T1, T2, T3> and BasicValidationPolicy<T3, T2, T1> being used would generate 7 distinct types in a hierarchy (the empty one is shared in both expansions). The same thing in the flatter hierarchy would be 5 distinct types - one for each of T1, T2, T3 and one for each combination. Adding in BasicValidationPolicy<T2, T3, T1> would add 3 more types recursively but 1 more type in the flat form.
The answer from #max66 isn't wrong, just something else to think about.
I am trying to get a better understanding of std::enable_if in C++11 and have been trying to write a minimal example: a class A with a member function void foo() that has different implementations based on the type T from the class template.
The below code gives the desired result, but I am not understanding it fully yet. Why does version V2 work, but not V1? Why is the "redundant" type U required?
#include <iostream>
#include <type_traits>
template <typename T>
class A {
public:
A(T x) : a_(x) {}
// Enable this function if T == int
/* V1 */ // template < typename std::enable_if<std::is_same<T,int>::value,int>::type = 0>
/* V2 */ template <typename U=T, typename std::enable_if<std::is_same<U,int>::value,int>::type = 0>
void foo() { std::cout << "\nINT: " << a_ << "\n"; }
// Enable this function if T == double
template <typename U=T, typename std::enable_if<std::is_same<U,double>::value,int>::type = 0>
void foo() { std::cout << "\nDOUBLE: " << a_ << "\n"; }
private:
T a_;
};
int main() {
A<int> aInt(1); aInt.foo();
A<double> aDouble(3.14); aDouble.foo();
return 0;
}
Is there a better way to achieve the desired result, i.e. for having different implementations of a void foo() function based on a class template parameter?
I know this wont fully answer your question, but it might give you some more ideas and understanding of how you can use std::enable_if.
You could replace your foo member functions with the following and have identical functionality:
template<typename U=T> typename std::enable_if<std::is_same<U,int>::value>::type
foo(){ /* enabled when T is type int */ }
template<typename U=T> typename std::enable_if<std::is_same<U,double>::value>::type
foo(){ /* enabled when T is type double */ }
A while back I gained a pretty good understanding of how enable_if works, but sadly I have forgotten most of its intricacies and just remember the more practical ways to use it.
As for the first question: why V1 doesn't work? SFINAE applies only in overload resolution - V1 however causes error at the point where type A is instantiated, well before foo() overload resolution.
I suppose there are lot's of possible implementations - which is the most appropriate depends on an actual case in question. A common approach would be to defer the part of A that's different for different template types to a helper class.
template <typename T>
class A_Helper;
template <>
class A_Helper<int> {
public:
static void foo( int value ){
std::cout << "INT: " << value << std::endl;
}
};
template <>
class A_Helper<double> {
public:
static void foo( double value ){
std::cout << "DOUBLE: " << value << std::endl;
}
};
template <typename T>
class A {
public:
A( T a ) : a_(a)
{}
void foo(){
A_Helper<T>::foo(a_);
}
private:
T a_;
};
The rest of A can be declared only once in a generic way - only the parts that differ are deferred to a helper. There is a lot of possible variations on that - depending on your requirements...
Assume the following template construction:
enum class ENUM {SINGLE, PAIR};
// General data type
template<ENUM T, class U>class Data;
// Partially specialized for single objects
template<class U>Data<ENUM::SINGLE, U> : public U {
// Forward Constructors, ...
};
// Partially specialized for pairs of objects
template<class U>Data<ENUM::PAIR, U> : public std::pair<U,U> {
// Forward Constructors, ...
};
In my code I want to be able to write something like
template<ENUM T>someMethod(Data<T, SomeClass> data) {
for_single_or_pair {
/*
* Use data as if it would be of type SomeClass
*/
}
}
which should do the same as the combination of the following methods:
template<>someMethod(Data<ENUM::SINGLE, SomeClass> data) {
data.doStuff();
}
template<>incrementData(Data<ENUM::PAIR, SomeClass> data) {
data.first.doStuff();
data.second.doStuff();
}
I.e. I want to be able to use a pair of objects (of the same type) as if it would be a single object. Of course I could reimplement the methods of a type T for Data<ENUM::PAIR, T> (see the answer of dau_sama) which for the given example would look like:
template<>Data<ENUM::PAIR, SomeClass> : public std::pair<SomeClass, SomeClass> {
doStuff() {
this->first.doStuff();
this->second.doStuff();
}
};
But I would have to do this for many methods and operators and many different types, although the methods and operators would all look like this example.
The syntax of the solution may be very different from what I wrote above, this is just to demonstrate what I want to achieve. I would prefer a solution without macros, but could also live with that.
Can such an abstraction be realized in C++11?
The reasons I want to do this are
I do not have to specialize templated methods that shall work for ENUM::Single and ENUM::PAIR when all differences between the specializations would math the pattern above (avoid a lot of code duplication).
The same pattern is occuring very often in my code and I could avoid implementing workarounds in many places, which would be almost identical in each case.
You could try to create a template method applyMethod. Here is a complete example. I used an Executor class containing only one static method because I could not find a better way to process methods taking any types of parameters
#include <iostream>
#include <string>
enum ENUM {SINGLE, PAIR};
// General data type
template<ENUM T, class U>class Data {
};
// Partially specialized for single objects
template<class U>
class UData : public Data<ENUM::SINGLE, U>, public U {
// Forward Constructors, ...
public:
UData(const U& u): U(u) {};
};
// Partially specialized for pairs of objects
template<class U>
class PData : public Data<ENUM::PAIR, U>, public std::pair<U,U> {
// Forward Constructors, ...
public:
PData(const U& u1, const U& u2): std::pair<U, U>(u1, u2) {};
};
template <class U, typename... P>
class Executor {
Executor() = delete;
public:
template<void (U::*M)(P... params)>
static void applyMethod(Data<ENUM::SINGLE, U> &data, P ...params) {
UData<U>& ud= reinterpret_cast<UData<U>& >(data);
U& u = static_cast<U&>(ud);
(u.*M)(params...);
}
template<void (U::*M)(P... params)>
static void applyMethod(Data<ENUM::PAIR, U> &data, P ...params) {
PData<U>& pd = reinterpret_cast<PData<U>& >(data);
(pd.first.*M)(params...);
(pd.second.*M)(params...);
}
};
class X {
std::string name;
public:
X(const std::string& name): name(name) { };
void doStuff(void) {
std::cout << "DoStuff : " << name << std::endl;
}
void doStuff(int i) {
std::cout << "DoStuff : " << name << " - " << i << std::endl;
}
};
int main() {
X x1("x1");
X x2("x2");
X x3("x3");
UData<X> data1(x1);
PData<X> data2(x2, x3);
Executor<X>::applyMethod<&X::doStuff>(data1);
Executor<X, int>::applyMethod<&X::doStuff>(data2, 12);
return 0;
}
You could add a common method to your classes
template<class U>
Data<ENUM::SINGLE, U> : public U {
// Forward Constructors, ...
void handle() {
//do some specific handling for this type
return;
}
};
Now someMethod will just call the right "handle" and it'll automatically switch between the two
template<typename T>
someMethod(T& data) {
data.handle();
}
//If you want to bind your function to some other name, you could
//create a functor that calls someMethod with the arguments passed in _1
//I haven't tested it, there might be some syntax problems with the way you pass in the function name
auto someOtherMethod = std::bind (someMethod, _1);
If your type doesn't implement a handle method, you'll have a nasty compilation error. If you want to provide a default implementation and avoid a compilation error, there is a common pattern called SFINAE (Substitution failure is not an error) that does exactly that.
Here's an alternative to the solution to that from Serge Ballesta, using lambdas.
#include <functional>
template<ENUM T, class U>void for_single_or_pair(
Data<T, U>& data,
std::function<void(U&)> function);
template<class U>void for_single_or_pair(
Data<ENUM::SINGLE, U>& data,
std::function<void(U&)> function) {
function(data);
}
template<class U>void for_single_or_pair(
Data<ENUM::PAIR, U>& data,
std::function<void(U&)> function) {
function(data.first);
function(data.second);
}
Usage:
template<ENUM T>someMethod(Data<T, SomeClass> data) {
for_single_or_pair(data,[](SomeClass& someObject) {
// Play around with someObject in any way
});
}
In this way additionally to use member methods of SomeClass, the data can be used in any other way.
I would be happy about comments to this solution (and if it could be generalized to use more than one Data inside the for_single_or_pair method).
My goal is to implement a container (here a set of stacks, one for each type) that accepts many different types of objects simultaneously. This would be trivial to do at runtime, using void pointers (or a common base class for all stored types) and runtime type indentification (RTTI). Since all types the container is going to hold are known at compile time, it may (or may not) be possible to make such a class using templates. I am aware that boost::variant already provides similar functionality, but it requires that the stored types are listed as template arguments, as in boost::variant< int, std::string > v;.
What I'm really looking for is a class that transparently adds a matching (internal) data strucure to itself each time a new template specialization of the equivalent of push() is created. The usage of the class would look like this:
int main()
{
MultiTypeStack foo;
//add a double to the container (in this case, a stack). The class would
//..create a matching std::stack<double>, and push the value to the top.
foo.push<double>(0.1);
//add an int to the container. In this case, the argument type is deduced.
//..The class would create a std::stack<int>, and push the value to the top.
foo.push(123);
//push a second double to the internal std::stack<double>.
foo.push<double>(3.14159);
std::cout << "int: " << foo.top<int>() << "\n"; //"int: 123"
std::cout << "double: " << foo.top<double>() << "\n";//"double: 3.14159"
return 0;
}
A naïve implementation as an example:
template<typename T> struct TypeIndex;
template<> struct TypeIndex<int>{enum{i = 0};};
template<> struct TypeIndex<double>{enum{i = 1};};
class MultiTypeStack
{
public:
template<typename T>
void push(const T &val){std::get<TypeIndex<T>::i>(stacks_).push(val);}
template<typename T>
void pop(){std::get<TypeIndex<T>::i>(stacks_).pop();}
template<typename T>
T top(){return std::get<TypeIndex<T>::i>(stacks_).top();}
private:
std::tuple<std::stack<int>, std::stack<double>> stacks_;
};
The problem with trying to use static polymorphism to implement a heterogeneous container of the kind you describe is that while "all types the container is going to hold are known at compile time," this information is not available until very late in the compilation process. In fact, thanks to C++'s translation unit model of compilation, you can only really depend on that type information being available at link time, which just screams virtual dispatch.
Realistically, I'd say the best way of accomplishing most of what you want without invoking Greenspun's Tenth Rule of Programming outright is to use the method of ad-hoc dynamic polymorphism (dynamically dispatching on a type without requiring that it inherit from a particular base class) outlined by Sean Parent in
his GoingNative 2013 talk. It does rely internally on full-blown inheritance-based dynamic typing, but it hides it all away and allows for stratifying the elements according to type with a little work. Expanding on #Yakk's
suggestion:
#include <stack>
#include <unordered_map>
#include <typeindex>
class MultiStack
{
class MultiStackBase
{
public:
virtual ~MultiStackBase () = default;
};
template <typename T>
class MultiStackImpl
: public MultiStackBase
{
std::stack <T> _stack;
public:
virtual ~MultiStackImpl () = default;
template <typename U>
void push (U&& new_element)
{ _stack.push (std::forward <U> (new_element)); }
void pop ()
{ _stack.pop (); }
T& top ()
{ return _stack.top (); }
const T& top () const
{ return _stack.top (); }
};
mutable std::unordered_map <std::type_index, std::unique_ptr <MultiStackBase>> stacks;
protected:
template <typename T>
static std::type_index index ()
{ return std::type_index {typeid (T)}; }
template <typename T>
MultiStackImpl <T>& stack_cast ()
{
if (stacks.count (index <T> ()) == 0)
stacks [index <T> ()] = std::make_unique <MultiStackImpl <T>> ();
return dynamic_cast <MultiStackImpl <T>&> (*stacks [index <T> ()]);
}
template <typename T>
const MultiStackImpl <T>& stack_cast () const
{
if (stacks.count (index <T> ()) == 0)
stacks [index <T> ()] = std::make_unique <MultiStackImpl <T>> ();
return dynamic_cast <const MultiStackImpl <T>&> (*stacks [index <T> ()]);
}
public:
template <typename T, typename U>
void push (U&& new_element)
{ stack_cast <T> ().push (std::forward <U> (new_element)); }
template <typename T>
void pop ()
{ stack_cast <T> ().pop (); }
template <typename T>
T& top ()
{ return stack_cast <T> ().top (); }
template <typename T>
const T& top () const
{ return stack_cast <T> ().top (); }
};
#include <iostream>
int main ()
{
MultiStack m;
m.push <int> (42);
m.push <float> (3.14);
std::cout << m.top <int> () << std::endl
<< m.top <float> () << std::endl;
}
we get the following output:
42
3.14
So unfortunately we did resort to dynamic typing and don't have template argument deduction as we'd like (you could have a deducing push, but I suspect it would be prone to subtle programmer errors; better to make it explicit), but we got the desired behaviour: a multi-type stack without enumerating types, letting instead the compiler determine them for us.
EDIT: I should point out that this approach has one potentially massive benefit over a statically typed implementation (if such a thing is even possible): with a purely static implementation, every object of type MultiStack would have a stack for every type used; for example, if you used a std::string in a MultiStack in one function, a MultiStack living in another would also have a std::string stack, and vice versa. Doing it this way, any given MultiStack object only allocates stacks for the types it uses.
Create an std::unordered_map<std::type_index, std::unique_ptr<unknown>>. Your typed access code takes the type and finds the appropiate entry. Then static_cast the unknown to a type dependent on T that holds your stack.
Make sure unknown is a base of stack_holder<T>, and that unknown has a virtual destructor.
This is probably not exactly what you want, but the C++ type system is pure: later expressions cannot change 'earlier' types.
If you chained the type you could construct a more complex type, but this is just listing the types while concealing them.
If the object is a singleton some hackery using static locals could work.
I have an implementation that is slightly different from what you requested, but maybe it will work for you. I made a list-like structure that when you try to add a new type of element into it either copies or moves itself into an enveloping container (of a different type) that can contain that new element type. (Like a persistent data structure in the copy case).
Here is the code. It is pretty ugly and I wasn't going to post it but no has answered at the time of writing so I can only hope someone can help make it better.
//Checks if list (or element) S has element of type T
template<class L, class T> struct HasElem : std::is_same<L,T>{};
template<template<class,class> class Node, class T, class NodeT, class Next>
struct HasElem<Node<NodeT,Next>,T>{
static constexpr bool value = std::is_same<NodeT,T>::value || HasElem<Next,T>::value;
};
template<template<class> class Leaf, class S, class T> struct HasElem<Leaf<S>,T> : std::is_same<S,T>{};
//Push type transform
template<class N, class T> struct Push{};
template<template<class,class> class Node, class T, class Next, class U> struct Push<Node<T,Next>,U>{
typedef Node<U,Node<T,Next>> type;
};
//Node type
template<class T, class Next>
struct Node{
Node(Next&& nxt) : next(nxt){}
Node(const Next& nxt) : next(nxt){}
std::stack<T> st;
Next next;
//Pushing a new type onto the stack
template<class U> typename std::enable_if<!HasElem<Node,U>::value,typename Push<Node,U>::type>::type
push(const U& u) &&{ //disallow pushing new types on lvalues
return typename Push<Node,U>::type(std::move(*this)).push(u);
}
//Pushing a new type onto the stack as an lvalue and return a copy
template<class U> typename std::enable_if<!HasElem<Node,U>::value,typename Push<Node,U>::type>::type
push_new(const U& u) const{ //cannot overload on && qualifier. Make the name uglier to warn of the cost
return typename Push<Node,U>::type(*this).push(u);
}
//Regular old push
Node& push(const T& t){ st.push(t); return *this; }
//Push onto another node in the list
template<class U> typename std::enable_if<HasElem<Node,U>::value,Node>::type
push(const U& u){ next.push(u); return *this; }
template<class U> typename std::enable_if<std::is_same<T,U>::value,U>::type&
top(){ return st.top(); }
template<class U> typename std::enable_if<!std::is_same<T,U>::value && HasElem<Node,U>::value,U>::type&
top(){ return next.top<U>(); }
};
//The last node. I made it hold data but it doesn't need to
template<class T> struct Leaf{
std::stack<T> st;
Leaf& push(const T& t){ st.push(t); return *this; }
template<class U> Node<U,Leaf> push(const U& u){
return Node<U,Leaf>(std::move(*this)).push(u);
}
template<class U> void top(){}
T& top(){ return st.top(); }
void pop(){ st.pop(); }
};
Here is an example of how to use it and hide away the difference between push and push_new.
template<class T, class Next, class U> auto push(Node<T,Next>&& n, const U& u)
-> decltype(n.push(u)){
return n.push(u);
}
template<class T, class Next, class U> auto push(const Node<T,Next>& n, const U& u)
-> decltype(n.push_new(u)){
return n.push_new(u);
}
int main(){
auto b = Leaf<int>().push<int>(42).push<double>(3.14).push<char>('a');
auto a = push(b,(char*)"Hello"); //Make a copy of b but with "Hello"
cout << a.top<int>() << " " << a.top<double>() << " " <<
a.top<char>() << " " << a.top<char*>() << endl;
cout << b.top<char>() << endl; //The earlier version b still exists
}
The major downside is that it will be inefficient if you save the intermediate states (i.e. into variables) but if you chain operations together like b in the example you can avoid it.
There were a couple of presentations at C++ Now 2013 describing how to implement dynamic containers in a static language like C++. They were:
1) Dynamic, Recursive, Heterogeneous Types in Statically-Typed Languages: paper and presentation
2) Dynamic C++ presentation
Those two folks also collaborated on a Dynamic C++ article for an online article for ACCU: Dynamic C++
There is plenty of information about how to build dynamic constructs for a static language like C++.
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.