2007-08-17 00:36:07 +02:00
|
|
|
/* try.cpp - for trying out some language features....
|
|
|
|
|
* scons will create the binary bin/try
|
|
|
|
|
*
|
2014-08-16 02:04:29 +02:00
|
|
|
*/
|
2007-08-17 00:36:07 +02:00
|
|
|
|
|
|
|
|
// 8/07 - how to control NOBUG??
|
2007-08-31 14:57:49 +02:00
|
|
|
// execute with NOBUG_LOG='ttt:TRACE' bin/try
|
2008-01-04 01:44:40 +01:00
|
|
|
// 1/08 - working out a static initialisation problem for Visitor (Tag creation)
|
2008-01-27 03:58:24 +01:00
|
|
|
// 1/08 - check 64bit longs
|
2008-04-05 05:57:54 +02:00
|
|
|
// 4/08 - comparison operators on shared_ptr<Asset>
|
2008-04-26 05:38:19 +02:00
|
|
|
// 4/08 - conversions on the value_type used for boost::any
|
2008-05-17 04:34:46 +02:00
|
|
|
// 5/08 - how to guard a downcasting access, so it is compiled in only if the involved types are convertible
|
2008-07-22 08:19:03 +02:00
|
|
|
// 7/08 - combining partial specialisation and subclasses
|
2008-10-26 03:21:33 +01:00
|
|
|
// 10/8 - abusing the STL containers to hold noncopyable values
|
2009-06-26 05:27:54 +02:00
|
|
|
// 6/09 - investigating how to build a mixin template providing an operator bool()
|
2009-12-31 01:21:45 +01:00
|
|
|
// 12/9 - tracking down a strange "warning: type qualifiers ignored on function return type"
|
2010-01-02 06:26:56 +01:00
|
|
|
// 1/10 - can we determine at compile time the presence of a certain function (for duck-typing)?
|
2010-04-09 07:44:31 +02:00
|
|
|
// 4/10 - pretty printing STL containers with python enabled GDB?
|
2011-01-08 03:30:10 +01:00
|
|
|
// 1/11 - exploring numeric limits
|
2011-01-20 13:21:14 +01:00
|
|
|
// 1/11 - integer floor and wrap operation(s)
|
2011-01-31 05:35:43 +01:00
|
|
|
// 1/11 - how to fetch the path of the own executable -- at least under Linux?
|
2011-10-09 14:52:58 +02:00
|
|
|
// 10/11 - simple demo using a pointer and a struct
|
2011-11-01 03:11:43 +01:00
|
|
|
// 11/11 - using the boost random number generator(s)
|
2011-12-30 03:45:10 +01:00
|
|
|
// 12/11 - how to detect if string conversion is possible?
|
2012-01-07 03:28:12 +01:00
|
|
|
// 1/12 - is partial application of member functions possible?
|
2014-05-09 00:49:15 +02:00
|
|
|
// 5/14 - c++11 transition: detect empty function object
|
2014-08-13 03:08:00 +02:00
|
|
|
// 7/14 - c++11 transition: std hash function vs. boost hash
|
2014-09-21 02:54:54 +02:00
|
|
|
// 9/14 - variadic templates and perfect forwarding
|
2014-11-22 03:31:59 +01:00
|
|
|
// 11/14 - pointer to member functions and name mangling
|
2015-08-12 02:31:41 +02:00
|
|
|
// 8/15 - Segfault when loading into GDB (on Debian/Jessie 64bit
|
2015-08-29 17:09:03 +02:00
|
|
|
// 8/15 - generalising the Variant::Visitor
|
2012-01-07 03:28:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @file try.cpp
|
2015-08-29 17:09:03 +02:00
|
|
|
** Design: how to generalise the Variant::Visitor to arbitrary return values.
|
2015-08-13 20:59:19 +02:00
|
|
|
**
|
2015-08-29 17:09:03 +02:00
|
|
|
** Our Variant template allows either for access by known type, or through accepting
|
|
|
|
|
** a classic GoF visitor. Problem is that in many extended use cases we rather want
|
|
|
|
|
** to apply \em functions, e.g. for a monadic flatMap on a data structure built from
|
|
|
|
|
** Variant records. (see our \link diff::GenNode external object representation \endlink).
|
|
|
|
|
** Since our implementation technique relies on a template generated interface anyway,
|
|
|
|
|
** a mere extension to arbitrary return values seems feasible.
|
2014-08-16 02:04:29 +02:00
|
|
|
**
|
2012-01-07 03:28:12 +01:00
|
|
|
*/
|
|
|
|
|
|
2015-08-29 17:09:03 +02:00
|
|
|
typedef unsigned int uint;
|
|
|
|
|
|
|
|
|
|
#include "lib/meta/typelist.hpp"
|
|
|
|
|
#include "lib/meta/generator.hpp"
|
|
|
|
|
#include "lib/format-util.hpp"
|
2015-08-29 18:10:18 +02:00
|
|
|
#include "lib/util.hpp"
|
2015-08-29 17:09:03 +02:00
|
|
|
|
2011-12-30 03:45:10 +01:00
|
|
|
#include <iostream>
|
2015-08-29 17:09:03 +02:00
|
|
|
#include <cstdarg>
|
2014-08-13 04:18:38 +02:00
|
|
|
#include <string>
|
2014-11-22 03:31:59 +01:00
|
|
|
|
2015-08-29 18:10:18 +02:00
|
|
|
using util::unConst;
|
2011-12-30 03:45:10 +01:00
|
|
|
using std::string;
|
2011-10-09 14:52:58 +02:00
|
|
|
using std::cout;
|
2011-11-01 03:11:43 +01:00
|
|
|
using std::endl;
|
2008-10-26 03:21:33 +01:00
|
|
|
|
2015-08-29 17:31:42 +02:00
|
|
|
|
|
|
|
|
template<typename RET>
|
|
|
|
|
struct VFunc
|
|
|
|
|
{
|
|
|
|
|
|
2015-08-29 17:09:03 +02:00
|
|
|
template<class VAL>
|
|
|
|
|
struct ValueAcceptInterface
|
|
|
|
|
{
|
2015-08-29 17:31:42 +02:00
|
|
|
virtual RET handle(VAL&) { /* do nothing */ return RET(); };
|
2015-08-29 17:09:03 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename TYPES>
|
|
|
|
|
using VisitorInterface
|
|
|
|
|
= lib::meta::InstantiateForEach<typename TYPES::List, ValueAcceptInterface>;
|
2015-08-29 17:31:42 +02:00
|
|
|
|
|
|
|
|
};
|
2014-09-21 02:54:54 +02:00
|
|
|
|
2015-08-29 18:10:18 +02:00
|
|
|
using lib::meta::NullType;
|
|
|
|
|
using lib::meta::Node;
|
|
|
|
|
|
|
|
|
|
template<typename TYPES>
|
|
|
|
|
struct ConstAll;
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
|
struct ConstAll<NullType>
|
|
|
|
|
{
|
|
|
|
|
typedef NullType List;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template<typename TY, typename TYPES>
|
|
|
|
|
struct ConstAll<Node<TY,TYPES>>
|
|
|
|
|
{
|
|
|
|
|
typedef Node<const TY, typename ConstAll<TYPES>::List> List;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2015-08-13 18:45:05 +02:00
|
|
|
|
2015-08-29 17:09:03 +02:00
|
|
|
template<class A, class B>
|
|
|
|
|
struct Var
|
2015-08-13 20:59:19 +02:00
|
|
|
{
|
2015-08-29 17:09:03 +02:00
|
|
|
A a;
|
|
|
|
|
B b;
|
|
|
|
|
|
|
|
|
|
using TYPES = lib::meta::Types<A,B>;
|
|
|
|
|
|
2015-08-29 17:31:42 +02:00
|
|
|
template<typename RET>
|
2015-08-29 18:10:18 +02:00
|
|
|
using VisitorFunc = typename VFunc<RET>::template VisitorInterface<TYPES>;
|
|
|
|
|
template<typename RET>
|
|
|
|
|
using VisitorConstFunc = typename VFunc<RET>::template VisitorInterface<ConstAll<typename TYPES::List>>;
|
|
|
|
|
|
|
|
|
|
using Visitor = VisitorFunc<void>;
|
|
|
|
|
using Predicate = VisitorConstFunc<bool>;
|
2015-08-29 17:31:42 +02:00
|
|
|
|
|
|
|
|
template<typename RET>
|
|
|
|
|
RET
|
2015-08-29 18:10:18 +02:00
|
|
|
accept (VisitorFunc<RET>& visitor)
|
2015-08-29 17:09:03 +02:00
|
|
|
{
|
2015-08-29 17:31:42 +02:00
|
|
|
typename VFunc<RET>::template ValueAcceptInterface<A>& visA = visitor;
|
|
|
|
|
typename VFunc<RET>::template ValueAcceptInterface<B>& visB = visitor;
|
2015-08-29 17:09:03 +02:00
|
|
|
visA.handle (a);
|
2015-08-29 17:31:42 +02:00
|
|
|
return visB.handle (b);
|
2015-08-29 17:09:03 +02:00
|
|
|
}
|
2015-08-29 18:10:18 +02:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
accept (Visitor& visitor)
|
|
|
|
|
{
|
|
|
|
|
accept<void> (visitor);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
accept (Predicate& visitor) const
|
|
|
|
|
{
|
|
|
|
|
typename VFunc<bool>::template ValueAcceptInterface<const A>& visA = visitor;
|
|
|
|
|
typename VFunc<bool>::template ValueAcceptInterface<const B>& visB = visitor;
|
|
|
|
|
return visA.handle (a)
|
|
|
|
|
&& visB.handle (b);
|
|
|
|
|
}
|
2015-08-29 17:09:03 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
operator string() const
|
|
|
|
|
{
|
|
|
|
|
return "Var("
|
|
|
|
|
+ util::str(a)
|
|
|
|
|
+ "|"
|
|
|
|
|
+ util::str(b)
|
|
|
|
|
+ ")";
|
|
|
|
|
}
|
|
|
|
|
};
|
2015-08-13 18:45:05 +02:00
|
|
|
|
2008-01-27 03:58:24 +01:00
|
|
|
|
2015-08-29 18:10:18 +02:00
|
|
|
using V = Var<int, string>;
|
|
|
|
|
|
2015-08-29 17:09:03 +02:00
|
|
|
class Visi
|
2015-08-29 18:10:18 +02:00
|
|
|
: public V::Visitor
|
2015-08-29 17:09:03 +02:00
|
|
|
{
|
2015-08-29 18:10:18 +02:00
|
|
|
virtual void handle(int& i) { ++i; }
|
|
|
|
|
virtual void handle(string& s) { s += "."; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class Predi
|
|
|
|
|
: public V::Predicate
|
|
|
|
|
{
|
|
|
|
|
virtual bool handle(int const& i) { return 0 == i % 2; }
|
|
|
|
|
virtual bool handle(string const& s) { return 0 == s.length() % 2; }
|
2015-08-29 17:09:03 +02:00
|
|
|
};
|
|
|
|
|
|
2009-06-26 05:27:54 +02:00
|
|
|
|
2014-08-16 02:04:29 +02:00
|
|
|
int
|
2011-12-30 03:45:10 +01:00
|
|
|
main (int, char**)
|
2011-10-09 14:52:58 +02:00
|
|
|
{
|
2015-08-29 17:09:03 +02:00
|
|
|
|
2015-08-29 18:10:18 +02:00
|
|
|
V var{12, "huii"};
|
2015-08-29 17:09:03 +02:00
|
|
|
cout << string(var)<<endl;
|
|
|
|
|
|
|
|
|
|
Visi visi;
|
2015-08-29 18:10:18 +02:00
|
|
|
Predi predi;
|
|
|
|
|
|
|
|
|
|
cout << var.accept(predi) <<endl;
|
|
|
|
|
var.accept(visi);
|
|
|
|
|
cout << var.accept(predi) <<endl;
|
2015-08-29 17:09:03 +02:00
|
|
|
cout << string(var)<<endl;
|
2014-08-17 03:23:35 +02:00
|
|
|
|
2008-10-26 22:35:01 +01:00
|
|
|
cout << "\n.gulp.\n";
|
2007-08-17 00:36:07 +02:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|