/* try.cpp - for trying out some language features.... * scons will create the binary bin/try * */ // 8/07 - how to control NOBUG?? // execute with NOBUG_LOG='ttt:TRACE' bin/try // 1/08 - working out a static initialisation problem for Visitor (Tag creation) // 1/08 - check 64bit longs // 4/08 - comparison operators on shared_ptr // 4/08 - conversions on the value_type used for boost::any // 5/08 - how to guard a downcasting access, so it is compiled in only if the involved types are convertible // 7/08 - combining partial specialisation and subclasses // 10/8 - abusing the STL containers to hold noncopyable values // 6/09 - investigating how to build a mixin template providing an operator bool() // 12/9 - tracking down a strange "warning: type qualifiers ignored on function return type" // 1/10 - can we determine at compile time the presence of a certain function (for duck-typing)? // 4/10 - pretty printing STL containers with python enabled GDB? // 1/11 - exploring numeric limits // 1/11 - integer floor and wrap operation(s) // 1/11 - how to fetch the path of the own executable -- at least under Linux? // 10/11 - simple demo using a pointer and a struct // 11/11 - using the boost random number generator(s) // 12/11 - how to detect if string conversion is possible? // 1/12 - is partial application of member functions possible? // 5/14 - c++11 transition: detect empty function object // 7/14 - c++11 transition: std hash function vs. boost hash // 9/14 - variadic templates and perfect forwarding // 11/14 - pointer to member functions and name mangling // 8/15 - Segfault when loading into GDB (on Debian/Jessie 64bit // 8/15 - generalising the Variant::Visitor // 1/16 - generic to-string conversion for ostream // 1/16 - build tuple from runtime-typed variant container // 3/17 - generic function signature traits, including support for Lambdas /** @file try.cpp ** Metaprogramming: unified treatment of functors, function references and lambdas. ** ** This investigation is a partial step towards #994 and became necessary to support ** Command definition by Lambda ** */ typedef unsigned int uint; #include "lib/format-cout.hpp" #include "lib/format-util.hpp" #include "lib/meta/function.hpp" #include #include using std::function; using std::placeholders::_1; using std::bind; using std::string; using std::tuple; ////////////////############# Investigation of implementation variants namespace lib { namespace meta { template struct _FuZ : _FuZ { }; /** Specialisation for a bare function signature */ template struct _FuZ { using Ret = RET; using Args = Types; using Sig = RET(ARGS...); }; /** Specialisation for using a function pointer */ template struct _FuZ : _FuZ { }; /** Specialisation when using a function reference */ template struct _FuZ : _FuZ { }; /** Specialisation to deal with member pointer to function */ template struct _FuZ : _FuZ { }; /** Specialisation to handle member pointer to const function; * indirectly this specialisation also handles lambdas, * as redirected by the main template (via `decltype`) */ template struct _FuZ : _FuZ { }; }}//namespace lib::meta using lib::meta::_FuZ; ////////////////############# Investigation of implementation variants int funny (uint i) { return -i+1; } struct Funky { int ii = 2; int fun (uint i2) { return ii + funny(i2); } int operator() (uint i2) { return 2*ii - fun(i2); } static int notfunny (uint i) { return 2*funny (i); } }; #define SHOW_TYPE(_TY_) \ cout << "typeof( " << STRINGIFY(_TY_) << " )= " << lib::meta::typeStr<_TY_>() < void showType (F) { using Sig = typename _FuZ::Sig; SHOW_TYPE (F); SHOW_TYPE (Sig); } using Fun = function; using Fuk = function; int main (int, char**) { Fun f1{funny}; Fun f2{&funny}; Fun f3{Funky::notfunny}; Fun f4{&Funky::notfunny}; auto memfunP = &Funky::fun; Fuk f5{memfunP}; Funky funk; Fun f6{bind (f5, funk, _1)}; auto lambda = [&](uint ii) { return funk.fun(ii); }; Fun f7{lambda}; showType (funny); showType (&funny); showType (Funky::notfunny); showType (memfunP); showType (lambda); showType (f7); cout << "\n\n-------\n"; SHOW_TYPE (decltype(&Funky::operator())); SHOW_TYPE (decltype(lambda)); SHOW_TYPE (_FuZ::Sig); cout << "\n.gulp.\n"; return 0; }