diff --git a/src/lib/meta/duck-detector.hpp b/src/lib/meta/duck-detector.hpp index b670538fc..5bc33d937 100644 --- a/src/lib/meta/duck-detector.hpp +++ b/src/lib/meta/duck-detector.hpp @@ -89,57 +89,85 @@ namespace lib { namespace meta { - /////////////////////////////TODO: still hard wired for a first test.... - - template - class DetectNested - { - - template - static Yes_t check(typename X::Core *); - template - static No_t check(...); - - public: - static const bool value = (sizeof(Yes_t)==sizeof(check(0))); - }; - - - template - class DetectMember - { - template - struct Probe - { }; - - template - static Yes_t check(Probe*); - template - static No_t check(...); - - public: - static const bool value = (sizeof(Yes_t)==sizeof(check(0))); - }; - - - template - class DetectFunSig - { - template - struct Probe - { }; - - template - static Yes_t check(Probe*); - template - static No_t check(...); - - public: - static const bool value = (sizeof(Yes_t)==sizeof(check(0))); - }; - - } // namespace meta } // namespace lib + + + + + + +/** Detector for a nested type. + * Defines a metafunction (template), allowing to detect + * if a type TY in question has a nested type or typedef + * with the given name. To answer this question, instantiate + * resulting HasNested_XXX template with the type in question + * and check the static bool value field. + */ +#define META_DETECT_NESTED(_TYPE_) \ + template \ + class HasNested_##_TYPE_ \ + { \ + \ + template \ + static Yes_t check(typename X::_TYPE_ *); \ + template \ + static No_t check(...); \ + \ + public: \ + static const bool value = (sizeof(Yes_t)==sizeof(check(0))); \ + }; + + + +/** Detector for a nested member (field or function). + * Defines a metafunction (template), allowing to detect + * the presence of a member with the given name within + * a type in question. + */ +#define META_DETECT_MEMBER(_NAME_) \ + template \ + class HasMember_##_NAME_ \ + { \ + template \ + struct Probe \ + { }; \ + \ + template \ + static Yes_t check(Probe * ); \ + template \ + static No_t check(...); \ + \ + public: \ + static const bool value = (sizeof(Yes_t)==sizeof(check(0))); \ + }; + + + +/** Detector for a specific member function. + * Defines a metafunction (template), allowing to detect + * the presence of a member function with the specific + * signature, as defined by the parameters. Note this + * check will probably fail if there are overloads + */ +#define META_DETECT_FUNCTION(_RET_TYPE_,_FUN_NAME_,_ARGS_) \ + template \ + class HasFunSig_##_FUN_NAME_ \ + { \ + template \ + struct Probe \ + { }; \ + \ + template \ + static Yes_t check(Probe * ); \ + template \ + static No_t check(...); \ + \ + public: \ + static const bool value = (sizeof(Yes_t)==sizeof(check(0))); \ + }; + + + #endif diff --git a/tests/40components.tests b/tests/40components.tests index 6fb0f0fa3..585be3d6f 100644 --- a/tests/40components.tests +++ b/tests/40components.tests @@ -182,7 +182,13 @@ return: 0 END -PLANNED "Duck typing support" DuckDetector_test < : Yes +out: HasNested_Core : No +out: HasMember_honk : Yes +out: HasMember_honk : Yes +out: HasFunSig_honk : Yes +out: HasFunSig_honk : No return: 0 END diff --git a/tests/lib/meta/duck-detector-test.cpp b/tests/lib/meta/duck-detector-test.cpp index 25312ca33..bf0c15f5a 100644 --- a/tests/lib/meta/duck-detector-test.cpp +++ b/tests/lib/meta/duck-detector-test.cpp @@ -23,7 +23,7 @@ #include "lib/test/run.hpp" #include "lib/meta/duck-detector.hpp" -#include "lib/util.hpp" /////////////TODO +#include "lib/util.hpp" #include @@ -31,30 +31,33 @@ namespace lib { namespace meta{ namespace test{ - - //using std::string; + using std::cout; using std::endl; namespace { // some test ducks.... + struct PropperGander { class Core; - PropperGander& honk(); + PropperGander& honk (long,long); }; + struct Propaganda { - void honk(); + void honk(float); }; - -#define DO_CHECK(_EXPR_) cout << STRINGIFY(_EXPR_) << "\t = " << _EXPR_::value << endl; + }//(End) with test ducks +#define SHOW_CHECK(_EXPR_) cout << STRINGIFY(_EXPR_) << "\t : " << (_EXPR_::value? "Yes":"No") << endl; + + /*********************************************************************************** * @test verify building predicates to detect properties of a type at compile time. @@ -65,19 +68,23 @@ namespace test{ */ class DuckDetector_test : public Test { + + META_DETECT_NESTED(Core); + META_DETECT_MEMBER(honk); + META_DETECT_FUNCTION(PropperGander&, honk, (long,long)); + + void run (Arg) { - DO_CHECK( DetectNested ); - DO_CHECK( DetectNested ); + SHOW_CHECK( HasNested_Core ); + SHOW_CHECK( HasNested_Core ); - DO_CHECK( DetectMember ); - DO_CHECK( DetectMember ); + SHOW_CHECK( HasMember_honk ); + SHOW_CHECK( HasMember_honk ); - DO_CHECK( DetectFunSig ); - DO_CHECK( DetectFunSig ); - - UNIMPLEMENTED ("detect the propaganda"); + SHOW_CHECK( HasFunSig_honk ); + SHOW_CHECK( HasFunSig_honk ); } };