Lumiera
0.pre.03
»edit your freedom«
|
Go to the source code of this file.
Metaprogramming helpers to check for specific properties of a type in question.
Building upon the "SFINAE" principle, it is possible to create metafunction templates, which answer some questions about a given type at compile time. A lot of generic predicates of this kind can be found in the <type_traits>
library (standard since C++11). At times though, you want to ask more specific questions, like e.g. "does this type provide an operation quack() "? Because, if we can get a bool
answer to such a question at compile time, we can use std::enable_if
to pick a special implementation based on the test result. Together, these techniques allow to adopt a duck-typed programming style, where an arbitrary object is allowed to enter a given API function, provided this object supports some specific operations.
While C++ certainly isn't a dynamic language and does not provide any kind of run time introspection, doing such check-and branch at compile time allows to combine flexibility as known from dynamic languages with static type safety, which is compelling. We can generate similar implementations for types not further related by inheritance. Building on this, we're able to emulate some of the features enabled by type classes (or "concepts").
Most of these trait templates rely on a creative use of function overloading. The C++ standard requires the compiler silently to drop any candidate of overload resolution which has gotten an invalid function signature as a result of instantiating a template (type). This rule allows us to set up kind of a "honey pot" for the compiler: we present two overloaded candidate functions with a different return type; by investigating the resulting return type we're able to figure out the overload actually picked by the compiler.
This header provides some pre-configured tests, available as macros. Each of them contains a template based on the described setup, containing a probe type expression at some point. The key is to build this probe expression in a way that it is valid if and only if the type in question exhibits a specific property.
All these detection building blocks are written such as to provide a bool member ::value
, which is in accordance to the conventions of modern C++ metaprogramming. I.e. you can directly use them within std::enable_if
false
value by default. Effectively this means that an error in the test expression might go unnoticed; you'd be better off explicitly checking the detection result by an unit test.There are several typical problems to care about
sizeof()
. In regular code, doing such on an incomplete type would provoke a compilation failure – however, here this code gets evaluated in a SFINAE context, which means, it will fail silently and thus produce a wrong detection result. This can be quite insidious when relying on the proper detection to pick the right implementation/specialisation; especially when instantiating mutually dependent templates, the distinction between "complete" and "incomplete" can be rather arbitrary while in the process of instantiation.Definition in file duck-detector.hpp.
#include "lib/meta/util.hpp"
Macros | |
#define | META_DETECT_EXTENSION_POINT(_FUN_) |
Detector for support of a free-function extension point. More... | |
#define | META_DETECT_FUNCTION(_RET_TYPE_, _FUN_NAME_, _ARGS_) |
Detector for a specific member function. More... | |
#define | META_DETECT_FUNCTION_ARGLESS(_FUN_) |
Detector for an argument-less member function with the given name. More... | |
#define | META_DETECT_FUNCTION_NAME(_FUN_NAME_) |
Detector for a member function with the given name. More... | |
#define | META_DETECT_MEMBER(_NAME_) |
Detector for a nested member (field or function). More... | |
#define | META_DETECT_NESTED(_TYPE_) |
Detector for a nested type. More... | |
#define | META_DETECT_OPERATOR_DEREF() |
Detector for a dereferentiation operator. More... | |
#define | META_DETECT_OPERATOR_INC() |
Detector for a prefix increment operator. More... | |
#define META_DETECT_NESTED | ( | _TYPE_ | ) |
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.
Definition at line 111 of file duck-detector.hpp.
#define META_DETECT_MEMBER | ( | _NAME_ | ) |
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.
Definition at line 134 of file duck-detector.hpp.
#define META_DETECT_FUNCTION | ( | _RET_TYPE_, | |
_FUN_NAME_, | |||
_ARGS_ | |||
) |
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.
Definition at line 161 of file duck-detector.hpp.
#define META_DETECT_FUNCTION_NAME | ( | _FUN_NAME_ | ) |
Detector for a member function with the given name.
Defines a metafunction (template), allowing to detect the presence of a member function with a specific name, but without imposing any additional constraints on arguments and return type. Yet a non-function member will not trigger this detector.
Definition at line 186 of file duck-detector.hpp.
#define META_DETECT_FUNCTION_ARGLESS | ( | _FUN_ | ) |
Detector for an argument-less member function with the given name.
Defines a metafunction (template), allowing to detect a member function taking no arguments, and with arbitrary return type.
decltype
) Definition at line 219 of file duck-detector.hpp.
#define META_DETECT_EXTENSION_POINT | ( | _FUN_ | ) |
Detector for support of a free-function extension point.
Defines a metafunction (template), allowing to probe if the type in question supports a specific extension point function. Typically such functions are injected by some type in a way to be picked up by ADL. The detection test works by forming an expression to invoke the extension point, passing the type given as template parameter as function argument. If this expression type checks, the extension point is assumed to be supported.
Definition at line 248 of file duck-detector.hpp.
#define META_DETECT_OPERATOR_DEREF | ( | ) |
Detector for a dereferentiation operator.
Works like member detection
Definition at line 269 of file duck-detector.hpp.
#define META_DETECT_OPERATOR_INC | ( | ) |
Detector for a prefix increment operator.
Definition at line 296 of file duck-detector.hpp.