Research: possiblity to detect a generic Lambda?
This commit is contained in:
parent
18553f22b2
commit
01937f9736
3 changed files with 77 additions and 52 deletions
|
|
@ -34,31 +34,21 @@
|
|||
// 3/17 - generic function signature traits, including support for Lambdas
|
||||
// 9/17 - manipulate variadic templates to treat varargs in several chunks
|
||||
// 11/17 - metaprogramming to detect the presence of extension points
|
||||
// 11/17 - detect generic lambda
|
||||
|
||||
|
||||
/** @file try.cpp
|
||||
** Metaprogramming: how to detect that a type in question exposes a free function extension point.
|
||||
** Since such an extension point is typically injected alongside with the type exposing the extension
|
||||
** point and intended to be picked up by ADL, all we have to check is if it is valid to invoke the
|
||||
** extension point function with an instance of the target type.
|
||||
**
|
||||
** There are two difficulties to overcome, though
|
||||
** - a function might return void. And while we may indeed pick up `void` from `decltype(expr)`,
|
||||
** there is not much we can do with a void type. The remedy is just to use this type as template
|
||||
** parameter on another template instantiation, which fails if this type can not legally be formed.
|
||||
** - we do not know how to get a value of the type to probe, in order to feed it into the extension
|
||||
** point function. Fortunately, the `std::declval<TYPE>()` function was included into the C++ language
|
||||
** for this very purpose.
|
||||
** Metaprogramming: is it possible to distinguish a generic lambda from something not a function at all?
|
||||
*/
|
||||
|
||||
typedef unsigned int uint;
|
||||
|
||||
#include "lib/format-cout.hpp"
|
||||
#include "lib/format-util.hpp"
|
||||
#include "lib/meta/duck-detector.hpp"
|
||||
#include "lib/meta/function.hpp"
|
||||
#include "lib/test/test-helper.hpp"
|
||||
|
||||
#include <functional>
|
||||
//#include <functional>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
|
||||
|
|
@ -108,49 +98,15 @@ class Fishy
|
|||
friend void fun1 (Fishy&);
|
||||
};
|
||||
|
||||
#define META_DETECT_EXTENSION_POINT(_FUN_) \
|
||||
template<typename TY> \
|
||||
class HasExtensionPoint_##_FUN_ \
|
||||
{ \
|
||||
template<typename X, \
|
||||
typename SEL = decltype( _FUN_(std::declval<X>()))>\
|
||||
struct Probe \
|
||||
{ }; \
|
||||
\
|
||||
template<class X> \
|
||||
static Yes_t check(Probe<X> * ); \
|
||||
template<class> \
|
||||
static No_t check(...); \
|
||||
\
|
||||
public: \
|
||||
static const bool value = (sizeof(Yes_t)==sizeof(check<TY>(0))); \
|
||||
};
|
||||
|
||||
|
||||
META_DETECT_EXTENSION_POINT (fun)
|
||||
META_DETECT_EXTENSION_POINT (fun1)
|
||||
|
||||
int
|
||||
main (int, char**)
|
||||
{
|
||||
fun1 (23);
|
||||
fun1 ();
|
||||
auto lamb1 = [](int i) { return double(i) / (i*i); };
|
||||
auto lamb2 = [](auto i) { return double(i) / (i*i); };
|
||||
|
||||
SHOW_EXPR ( HasExtensionPoint_fun<long>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<long>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<long&>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<long&&>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<char>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<char&>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<char&&>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<string>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<void>::value );
|
||||
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<Cheesy>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<Fishy>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<Fishy&>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<Fishy&&>::value );
|
||||
SHOW_EXPR ( HasExtensionPoint_fun1<Fishy const&>::value );
|
||||
SHOW_TYPE (decltype(lamb1));
|
||||
SHOW_TYPE (decltype(lamb2));
|
||||
|
||||
cout << "\n.gulp.\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -311,6 +311,13 @@ namespace test{
|
|||
treeExplore(CountDown{5})
|
||||
.expand([](CountDown const& core){ return CountDown{ yield(core) - 1}; })
|
||||
);
|
||||
|
||||
#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1117
|
||||
verify_treeExpandingIterator(
|
||||
treeExplore(CountDown{5})
|
||||
.expand([](auto & it){ return CountDown{ *it - 1}; })
|
||||
);
|
||||
#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #1117
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -5188,6 +5188,68 @@
|
|||
<node CREATED="1511402855174" ID="ID_386377958" MODIFIED="1511402861001" TEXT="beides können unterschiedliche Typen sein"/>
|
||||
<node CREATED="1511402861613" ID="ID_1536434222" MODIFIED="1511402872072" TEXT="solange der expandFunktor beide akzeptiert...."/>
|
||||
</node>
|
||||
<node CREATED="1511455454190" ID="ID_1384978479" MODIFIED="1511455481991" TEXT="Problem: kein generischer Expand-Functor">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<node CREATED="1511455484027" ID="ID_548359395" MODIFIED="1511455605340" TEXT="unmittelbare Folge davon, daß wir den Typ des Expand-Funktors analysieren">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
_fun<FUN>::Sig scheitert
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="info"/>
|
||||
</node>
|
||||
<node CREATED="1511455502648" ID="ID_1704619802" MODIFIED="1511455566686">
|
||||
<richcontent TYPE="NODE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
das ist aber <i>unpraktisch</i>....
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
<icon BUILTIN="smily_bad"/>
|
||||
</node>
|
||||
<node CREATED="1511455513119" ID="ID_128446946" MODIFIED="1511455554663" TEXT="denn grade Iterator-Typen kennt der Benutzer typischerweise nicht">
|
||||
<richcontent TYPE="NOTE"><html>
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<p>
|
||||
....also ist es gradezu natürlich,
|
||||
</p>
|
||||
<p>
|
||||
einen Expand-Funktor als generisches Lambda zu schreiben!
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
</richcontent>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1511455607914" HGAP="56" ID="ID_1866082603" MODIFIED="1511455626668" TEXT="Untersuchung" VSHIFT="39">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node CREATED="1511455644829" ID="ID_1545300823" MODIFIED="1511455655796" TEXT="ist generisches Labmda detektierbar?">
|
||||
<icon BUILTIN="help"/>
|
||||
</node>
|
||||
<node CREATED="1511455664043" ID="ID_1966980711" MODIFIED="1511455676078" TEXT="kann man Fallback-Mechanismus bauen?">
|
||||
<icon BUILTIN="help"/>
|
||||
<node CREATED="1511455698398" ID="ID_91244603" MODIFIED="1511455735493" TEXT="wenn generisch...">
|
||||
<icon BUILTIN="idea"/>
|
||||
<node CREATED="1511455705149" ID="ID_1094783485" MODIFIED="1511455710889" TEXT="dann versuche"/>
|
||||
<node CREATED="1511455711525" ID="ID_1584168712" MODIFIED="1511455721127" TEXT="(a) mit dem Value-Type ins Argument"/>
|
||||
<node CREATED="1511455721907" ID="ID_312038081" MODIFIED="1511455730558" TEXT="(b) mit dem Iterator-Typ ins Argument"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1510969031379" ID="ID_358406634" MODIFIED="1511227807158" TEXT="verify_transformOperation();">
|
||||
|
|
|
|||
Loading…
Reference in a new issue