diff --git a/README.md b/README.md index 0a8d261..f6fbcdb 100644 --- a/README.md +++ b/README.md @@ -16,22 +16,6 @@ CallableTraits is a small, header-only library providing a uniform and comprehen ## Documentation [Here](http://badair.github.io/callable_traits/index.html) -## Compatibility - -CallableTraits is currently tested and working on the following platforms, unless otherwise noted: -- GNU/Linux - - clang 3.5 and later (both libc++ and libstdc++) - - gcc 5.2 and later -- OSX - - Apple Xcode 6.3 and later - - open-source clang 3.5 and later should work, but is not tested -- Windows - - Microsoft Visual Studio 2015 (native MSVC) - - MinGW32 gcc 5.3 (other versions not tested) - - clang-cl in Visual Studio's LLVM toolkit cannot build CallableTraits tests because of [this curious bug](http://stackoverflow.com/questions/36026352/compiler-attribute-stuck-on-a-function-type-is-there-a-workaround-for-this-cla). I filed a bug report, but I should be able to work around it when I find the time to do so. - -I do not know the compatibility of CallableTraits for other/older compilers, but the `stdlib` implementation must include `std::index_sequence` and friends. - ## Building the tests and examples First, you'll need a recent version of [CMake](https://cmake.org/). These commands assume that `git` and `cmake` are available in your environment path. If you need help with this, [message me on Gitter](https://gitter.im/badair/callable_traits). diff --git a/doc/callable_traits.qbk b/doc/callable_traits.qbk index 581084d..cd4e807 100644 --- a/doc/callable_traits.qbk +++ b/doc/callable_traits.qbk @@ -13,10 +13,16 @@ [lang en] ] + + [/ developer: you should enable word wrap before you read further] + + + [template libname[][^CallableTraits]] -[template libns[][^callable_traits::]] +[template lib_namespace[][^callable_traits]] +[template namespace_scoped[][^callable_traits::]] [template header_include_prefix[]callable_traits/] [template detail_open_include[] `#include<`[^[header_include_prefix]]] [template detail_close_include[]`.hpp>`] @@ -26,6 +32,85 @@ [template feedback[][link callable_traits.contact feedback]] [template repo[][@https://github.com/badair/callable_traits GitHub]] +[template link_msvc_issues[][link callable_traits.compatibility.msvc_issues MSVC Issues]] + +[/ *** these templates are used to turn concept names green ***] +[template concept_fn_ptr[][role green FunctionPtr]] +[template concept_fn_ref[][role green FunctionReference]] +[template concept_simple_fn[][role green UnqualifiedFunction]] +[template concept_abominable[][role green AbominableFunction]] +[template concept_fn[][role green Function]] +[template concept_pmf[][role green MemberFunctionPtr]] +[template concept_pmd[][role green MemberDataPtr]] +[template concept_member_ptr[][role green MemberPtr]] +[template concept_simple_fn_obj[][role green SimpleFunctionObject]] +[template concept_overloaded_fn_obj[][role green OverloadedFunctionObject]] +[template concept_fn_obj[][role green FunctionObject]] +[template concept_simple_callable[][role green SimpleCallable]] +[template concept_simple_invokable[][role green SimpleInvokable]] +[template concept_callable[][role green Callable]] +[template concept_invokable[][role green Invokable]] +[template concept_constexpr_constructible[][role green ConstexprDefaultConstructible]] +[template concept_cc_tag[][role green CallingConventionTag]] + +[/ *** concept links *** ] +[template link_fn_ptr[][link callable_traits.concepts.ref_fn_ptr [concept_fn_ptr]]] +[template link_fn_ref[][link callable_traits.concepts.ref_fn_ref [concept_fn_ref]]] +[template link_simple_fn[][link callable_traits.concepts.ref_simple_fn [concept_simple_fn]]] +[template link_abominable[][link callable_traits.concepts.ref_abominable [concept_abominable]]] +[template link_fn[][link callable_traits.concepts.ref_fn [concept_fn]]] +[template link_pmf[][link callable_traits.concepts.ref_pmf [concept_pmf]]] +[template link_pmd[][link callable_traits.concepts.ref_pmd [concept_pmd]]] +[template link_member_ptr[][link callable_traits.concepts.ref_member_ptr [concept_member_ptr]]] +[template link_simple_fn_obj[][link callable_traits.concepts.ref_simple_fn_obj [concept_simple_fn_obj]]] +[template link_overloaded_fn_obj[][link callable_traits.concepts.ref_overloaded_fn_obj [concept_overloaded_fn_obj]]] +[template link_fn_obj[][link callable_traits.concepts.ref_fn_obj [concept_fn_obj]]] +[template link_simple_callable[][link callable_traits.concepts.ref_simple_callable [concept_simple_callable]]] +[template link_simple_invokable[][link callable_traits.concepts.ref_simple_invokable [concept_simple_invokable]]] +[template link_callable[][link callable_traits.concepts.ref_callable [concept_callable]]] +[template link_invokable[][link callable_traits.concepts.ref_invokable [concept_invokable]]] +[template link_constexpr_constructible[][link callable_traits.concepts.ref_constexpr_constructible [concept_constexpr_constructible]]] +[template link_cc_tag[][link callable_traits.concepts.ref_cc_tag [concept_cc_tag]]] + +[/ *** reference links *** ] +[template link_add_calling_convention[][link callable_traits.ref_add_calling_convention [^add_calling_convention]]] +[template link_add_function_const[][link callable_traits.ref_add_function_const [^add_function_const]]] +[template link_add_function_cv[][link callable_traits.ref_add_function_cv [^add_function_cv]]] +[template link_add_function_lvalue[][link callable_traits.ref_add_function_lvalue [^add_function_lvalue]]] +[template link_add_function_rvalue[][link callable_traits.ref_add_function_rvalue [^add_function_rvalue]]] +[template link_add_varargs[][link callable_traits.ref_add_varargs [^add_varargs]]] +[template link_add_function_volatile[][link callable_traits.ref_add_function_volatile [^add_function_volatile]]] +[template link_apply_member_pointer[][link callable_traits.ref_apply_member_pointer [^apply_member_pointer]]] +[template link_apply_return[][link callable_traits.ref_apply_return [^apply_return]]] +[template link_arg_at[][link callable_traits.ref_arg_at [^arg_at]]] +[template link_args[][link callable_traits.ref_args [^args]]] +[template link_arity[][link callable_traits.ref_arity [^arity]]] +[template link_bind[][link callable_traits.ref_bind [^bind]]] +[template link_can_invoke[][link callable_traits.ref_can_invoke [^can_invoke]]] +[template link_can_invoke_constexpr[][link callable_traits.ref_can_invoke_constexpr [^can_invoke_constexpr]]] +[template link_function_type[][link callable_traits.ref_function_type [^function_type]]] +[template link_has_calling_convention[][link callable_traits.ref_has_calling_convention [^has_calling_convention]]] +[template link_has_varargs[][link callable_traits.ref_has_varargs [^has_varargs]]] +[template link_has_void_return[][link callable_traits.ref_has_void_return [^has_void_return]]] +[template link_is_const_qualified[][link callable_traits.ref_is_const_qualified [^is_const_qualified]]] +[template link_is_constexpr[][link callable_traits.ref_is_constexpr [^is_constexpr]]] +[template link_is_lvalue_qualified[][link callable_traits.ref_is_lvalue_qualified [^is_lvalue_qualified]]] +[template link_is_reference_qualified[][link callable_traits.ref_is_reference_qualified [^is_reference_qualified]]] +[template link_is_rvalue_qualified[][link callable_traits.ref_is_rvalue_qualified [^is_rvalue_qualified]]] +[template link_is_qualified[][link callable_traits.ref_is_qualified [^is_qualified]]] +[template link_is_volatile_qualified[][link callable_traits.ref_is_volatile_qualified [^is_volatile_qualified]]] +[template link_max_arity[][link callable_traits.ref_max_arity [^max_arity]]] +[template link_min_arity[][link callable_traits.ref_min_arity [^min_arity]]] +[template link_qualified_function_type[][link callable_traits.ref_qualified_function_type [^qualified_function_type]]] +[template link_remove_calling_convention[][link callable_traits.ref_remove_calling_convention [^remove_calling_convention]]] +[template link_remove_function_const[][link callable_traits.ref_remove_function_const [^remove_function_const]]] +[template link_remove_function_cv[][link callable_traits.ref_remove_function_cv [^remove_function_cv]]] +[template link_remove_member_pointer[][link callable_traits.ref_remove_member_pointer [^remove_member_pointer]]] +[template link_remove_function_reference[][link callable_traits.ref_remove_function_reference [^remove_function_reference]]] +[template link_remove_varargs[][link callable_traits.ref_remove_varargs [^remove_varargs]]] +[template link_remove_function_volatile[][link callable_traits.ref_remove_function_volatile [^remove_function_volatile]]] +[template link_result_of[][link callable_traits.ref_result_of [^result_of]]] + [template cc_warning_rationale[] The rationale for classifying the calling convention features as "experimental" is three-fold: @@ -50,50 +135,15 @@ It is the author's hope that future versions of [libname] will offer a stable, t ] ] - -[/ *** concepts *** ] - -[template concept_fn_obj[][role green FunctionObject]] -[template concept_overloaded_fn_obj[][role green OverloadedFunctionObject]] -[template concept_simple_fn_obj[][role green SimpleFunctionObject]] -[template concept_pmf[][role green MemberFunctionPtr]] -[template concept_pmd[][role green MemberDataPtr]] -[template concept_member_ptr[][role green MemberPtr]] -[template concept_fn[][role green Function]] -[template concept_abominable[][role green AbominableFunction]] -[template concept_fn_ptr[][role green FunctionPtr]] -[template concept_fn_ref[][role green FunctionReference]] -[template concept_simple_callable[][role green SimpleCallable]] -[template concept_simple_invokable[][role green SimpleInvokable]] -[template concept_callable[][role green Callable]] -[template concept_invokable[][role green Invokable]] -[template concept_constexpr_constructible[][role green ConstexprDefaultConstructible]] - -[/ *** concept links *** ] - -[template link_fn_obj[][link ref_fn_obj [concept_fn_obj]]] -[template link_overloaded_fn_obj[][link ref_overloaded_fn_obj [concept_overloaded_fn_obj]]] -[template link_simple_fn_obj[][link ref_simple_fn_obj [concept_simple_fn_obj]]] -[template link_pmf[][link ref_pmf [concept_pmf]]] -[template link_pmd[][link ref_pmd [concept_pmd]]] -[template link_member_ptr[][link ref_member_ptr [concept_member_ptr]]] -[template link_fn[][link ref_fn [concept_fn]]] -[template link_abominable[][link ref_abominable [concept_abominable]]] -[template link_fn_ptr[][link ref_fn_ptr [concept_fn_ptr]]] -[template link_fn_ref[][link ref_fn_ref [concept_fn_ref]]] -[template link_simple_callable[][link ref_simple_callable [[concept_simple_callable]]]] -[template link_simple_invokable[][link ref_simple_invokable [concept_simple_invokable]]] -[template link_callable[][link ref_callable [concept_callable]]] -[template link_invokable[][link ref_invokable [concept_invokable]]] -[template link_constexpr_constructible[][link ref_constexpr_constructible [concept_constexpr_constructible]]] - [section:introduction Introduction] -[important [libname] is not a Boost library.] +[libname] is a cross-platform C++14 library for the inspection, decomposition, and synthesis of C++ callable types. [libname] is header-only, and does not depend on any non-standard headers. [libname] is currently hosted at [repo]. -[libname] is a cross-platform C++14 library for the inspection, decomposition, and synthesis of C++ callable types. [libname] is header-only, and does not depend on any non-standard headers. +[note [libname] is not a Boost library.] -This documentation will be most beneficial to readers with a basic understanding of the syntax and usage of the following C++ features: +[section:prereqs Prerequisite Topics] + +This documentation will be most beneficial to readers who posess a basic understanding of the following C++ features: * [@http://en.cppreference.com/w/cpp/language/partial_specialization template specializations] * [@http://en.cppreference.com/w/cpp/language/sfinae SFINAE] @@ -107,11 +157,11 @@ This documentation will be most beneficial to readers with a basic understanding * [@https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers universal references] and [@http://stackoverflow.com/questions/13725747/concise-explanation-of-reference-collapsing-rules-requested-1-a-a-2 reference collapsing rules] * [@http://en.cppreference.com/w/cpp/language/member_functions#const-.2C_volatile-.2C_and_ref-qualified_member_functions cv-qualified and ref-qualified member functions] * [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0172r0.html "abominable" function types] -* [@http://en.cppreference.com/w/cpp/language/overloaded_address taking the address of an overloaded function] +* [@http://en.cppreference.com/w/cpp/language/overloaded_address taking the address of overloaded functions] * [@http://en.cppreference.com/w/c/language/variadic C-style variadics], a.k.a. varargs * [@https://en.wikipedia.org/wiki/X86_calling_conventions calling conventions] -The [libname] development repository is hosted at [repo]. +[endsect][/section:prereqs] [section:motivation Motivation] @@ -130,54 +180,198 @@ Template specializations like those in the code snippet above ['still] do not ac The use cases for [libname] are closely related to those of [@http://www.boost.org/doc/libs/1_60_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html function_traits] and [@http://www.boost.org/doc/libs/1_60_0/libs/function_types/doc/html/index.html Boost.FunctionTypes]. -[endsect] +[endsect][/section:motivation] -[section Quick Example] +[section:quick_example Quick Example] [import ../example/intro.cpp] [intro] -[endsect] +[endsect][/section:quick_example] -[section:basic_concepts Concept Definitions] +[section:reasons What makes [libname] unique?] -[libname] relies on the following concepts, and will be referenced throughout this documentation: +[*1.] [libname] offers template aliases such as [link_remove_function_const] for manipulating function qualifiers, designed to parallel the `` aliases such as `std::remove_const_t`. -[heading:ref_fn_ptr [concept_fn_ptr]] +[*2.] [libname] is designed to accept cv-qualified and ref-qualified types, which eliminates the need to prepare template argument types with metafunctions such as `std::remove_reference` and `std::decay`. This is especially useful when dealing with perfectly-forwarded parameter types in function templates. + +[*3.] [libname] is designed to comply with [invoke] rules, with one unobtrusive and beneficial deviation: [link_fn] types types are compatible with all relevant type operations that do not specifically require an invocation. + +[*4.] [namespace_scoped][link_arg_at]`<2, Callable>` is more flexible (arguable more readable) than `typename boost::function_traits::arg3_type`. + +[*5.] [link_can_invoke] is used to test `INVOKE`-ability at compile-time, with value semantics. For the craziest metaprogrammers, [link_can_invoke_constexpr] does the same as `can_invoke` for [link_constexpr_constructible] types, with an added check for `constexpr`-ness (Note: for `can_invoke_constexpr`, argument types must also be [link_constexpr_constructible]) + +[*6.] [link_is_constexpr] is used to check whether a [link_constexpr_constructible] type is a [link_callable] type that yields a `constexpr` result -- no arguments necessary. + +[*7.] [link_bind] is used by library writers to easily accept `std::placeholder` expressions anywhere, and intercept the type information for processing before forwarding on to `std::bind` or `boost::bind`. This gives library writers the power to create more flexible templated APIs. + +[*8.] [link_min_arity] is used to detect the presence of default arguments on a [link_simple_fn_obj] + +[*9.] The [libname] interface mainly consists of template aliases and `constexpr std::integral_constant` functions, which are arguably preferable to `typename foo::type` and `foo::value`. While the `std::integral_constant` functions in [libname] may be a deviation from traditional type trait designs, they facilitate a metaprogramming style that uses value-semantics (a la [hana]). The functions can generally be used with either types or values, which eliminates unnecessary `decltype` usage. + +[*10.] [libname] includes optional features for the manipulation and inspection of calling conventions. These features are currently deemed experimental, because they greatly increase the test surface of [libname], are platform-specific, and are not yet fully tested on any platform. + +[endsect][/section:reasons] + +[endsect][/section:introduction] + + + +[/*********************************************************************] +[/**************** U S E C A S E E X A M P L E ********************] +[/*********************************************************************] + +[section:function_sugar_example Example:[^ std::function] sugar] + +At a glance, there appear to be around 260 [@http://stackoverflow.com/search?q=convert+std%3A%3Abind+to+std%3A%3Afunction search results] on Stack Overflow concerning the conversion from `std::bind` to `std::function`, and around 340 [@http://stackoverflow.com/search?q=convert+lambda+to+std%3A%3Afunction search results] concerning the conversion of lambdas to `std::function`. However misguided these questions might be, we'll kill both birds with the same stone with the `make_function` example below, which will leverage [libname] to... + +# Construct an `std::function` where T is not explicitly supplied by the user +# Construct an `std::function` where T is the deduced "signature" of an `std::placeholders` expression + +Without real-world context, `make_function` may seem rather silly, especially since we are needlessly incurring the runtime cost of type erasure, which takes place inside the `std::function` implementation. However, this `make_function` might be useful in a situation where `std::function` would be required by some 3rd party API. + +[note Due to limitations in the Microsoft compiler, this example will not compile with MSVC. For more information, refer to the [link_msvc_issues] section.] + +[import ../example/make_function.cpp] +[make_function] + +[endsect][/section:function_sugar_example] + + + +[/*********************************************************************] +[/******************* C O M P A T I B I L I T Y ***********************] +[/*********************************************************************] + +[section:compatibility Compatibility] + +[libname] is currently tested and working on the following platforms, unless otherwise noted: + +[table Supported Platforms + [[Operating System] [Compilers]] + [ + [Linux] + [ + - Clang 3.5 and later (both libc++ and libstdc++) + + - GCC 5.2 and later + ] + ] + + [ + [OSX] + [ + - Apple Clang in Xcode 6.3 and later + + - open-source Clang 3.5 and later should work, but is not yet tested + ] + ] + + [ + [Windows] + [ + - Microsoft Visual Studio 2015 - Clang-cl + + - Microsoft Visual Studio 2015 - native MSVC - partial support (see below) + + - MinGW GCC 5.3 (other versions not tested) + ] + ] +] + +[template msvc_disabled_functions[] + + +* [link_bind] +] + +[note ] + +See the most recent cross-platform integration test results [@https://travis-ci.org/badair/callable_traits here] at Travis CI. Currently, Travis CI does not support Windows -- all Windows testing is performed locally on the author's Windows 10 machine. + +CallableTraits has not been tested on every platform under the sun. If you find CallableTraits to work with another toolchain, [link callable_traits.contact let us know!] + +[section:msvc_issues MSVC Issues] + +While most of the features in [libname] are tested and working in MSVC, the following 3 functions do not work: + +* [link_is_constexpr] - always returns an instance of `std::false_type` in MSVC +* [link_can_invoke_constexpr] - always returns an instance of `std::false_type` in MSVC +* [link_bind] - the aliased types inside the return type of this function are bugged. A static_assert will trigger if this function is used in MSVC. + +[endsect][/section:msvc_issues] + +[endsect][/section:compatibility] + + + +[/*********************************************************************] +[/*********************** C O N C E P T S *****************************] +[/*********************************************************************] + +[section:concepts Concepts] + +[libname] relies on the following concepts, which will be cross-referenced throughout the documentation. Concepts will always be formatted with [role green green] text. + +[section:ref_fn_ptr [concept_fn_ptr]] * Any function pointer type * the pointer may be cv-qualified and/or ref-qualified * e.g. `void(*)(int, int)` or `void(* const &)(int, int)` -[heading:ref_fn_ref [concept_fn_ref]] +[endsect] + +[section:ref_fn_ref [concept_fn_ref]] * Any function reference type * e.g. `void(&)(int, int)` -[heading:ref_fn [concept_fn]] +[endsect] + +[section:ref_simple_fn [concept_simple_fn]] * Any unqualified function type * e.g. `void(int, int)` -[heading:ref_abominable [concept_abominable]] +[endsect] + +[section:ref_abominable [concept_abominable]] * Any qualified (a.k.a. [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0172r0.html "abominable"]) function type * Not technically "callable", but still falls under the [libname] umbrella -* Mutually exclusive with [link_fn] +* Mutually exclusive with [link_simple_fn] * e.g. `void(int, int) const` -[heading:ref_pmf [concept_pmf]] +[endsect] + +[section:ref_fn [concept_fn]] +* The superset of [link_simple_fn] and [link_abominable] + +[endsect] + +[section:ref_pmf [concept_pmf]] * Any pointer to member function type * The pointer type may be cv-qualified and/or ref-qualified * e.g. `void (foo::*)(int, int)` -[heading:ref_pmd [concept_pmd]] +[endsect] + +[section:ref_pmd [concept_pmd]] * Any pointer to data member type * The pointer type may be cv-qualified and/or ref-qualified * e.g. `int foo::*` -[heading:ref_simple_fn_obj [concept_simple_fn_obj]] +[endsect] + +[section:ref_member_ptr [concept_member_ptr]] +* The superset of [link_pmf] and [link_pmd] + +[endsect] + +[section:ref_simple_fn_obj [concept_simple_fn_obj]] * Any class/struct with a ['non-templated, non-overloaded] function call operator * Includes non-generic lambda types * May be cv-qualified and/or ref-qualified. * Mutually exclusive with [link_overloaded_fn_obj] * e.g. the type of this lambda: `[](int x, int y) { return x + y; }` -[heading:ref_overloaded_fn_obj [concept_overloaded_fn_obj]] +[endsect] + +[section:ref_overloaded_fn_obj [concept_overloaded_fn_obj]] * Any class/struct with a ['templated or overloaded] function call operator, with the following limitation for those with templated function call operators (which includes generic lambdas): * If templated , all instantiations must be [@http://stackoverflow.com/questions/35033306/what-does-it-mean-when-one-says-something-is-sfinae-friendly SFINAE-friendly], and must not use [@http://en.cppreference.com/w/cpp/language/indent_name dependent names], except where the dependent "names" are C++ operators. * May be cv-qualified and/or ref-qualified @@ -185,74 +379,61 @@ The use cases for [libname] are closely related to those of [@http://www.boost.o [tip Generic lambdas or classes with templated function objects that are either not SFINAE-friendly or rely on dependent names for template instantiations are generally incompatible with [libname].] -[heading:ref_fn_obj [concept_fn_obj]] +[endsect] + +[section:ref_fn_obj [concept_fn_obj]] * Any type that is either an [link_overloaded_fn_obj] or a [link_simple_fn_obj] -[heading:ref_callable [concept_callable]] +[endsect] + +[section:ref_callable [concept_callable]] * The superset of the following: * [link_fn_ptr] * [link_fn_ref] * [link_fn] - * [link_abominable] * [link_pmf] * [link_pmd] * [link_fn_obj] -[heading:ref_simple_callable [concept_simple_callable]] -* Includes all [link_callable] types, [*except] for [link_overloaded_fn_obj] +[endsect] + +[section:ref_simple_callable [concept_simple_callable]] +* Includes all [link_callable] types, [*excluding] [link_overloaded_fn_obj] -[heading:ref_simple_invokable [concept_simple_invokable]] -* Includes all [link_callable] types, [*except] for [link_overloaded_fn_obj], [link_fn], and [link_abominable] +[endsect] -[heading:ref_invokable [concept_invokable]] -* Includes all [link_callable] types, [*except] for [link_fn] and [link_abominable] +[section:ref_simple_invokable [concept_simple_invokable]] +* Includes all [link_callable] types, [*excluding] [link_overloaded_fn_obj] and [link_fn] -[heading:ref_constexpr_constructible [concept_constexpr_constructible]] +[endsect] + +[section:ref_invokable [concept_invokable]] +* Includes all [link_callable] types, [*excluding] [link_fn] + +[endsect] + +[section:ref_constexpr_constructible [concept_constexpr_constructible]] * Any [@http://en.cppreference.com/w/cpp/concept/LiteralType LiteralType] that is also default-constructible [endsect] -[section:reasons Why use [libname]?] - -[*1.] [libname] offers template aliases such as `remove_function_const` for manipulating function qualifiers, designed to parallel the `` aliases such as `std::remove_const_t`. - -[*2.] [libname] is designed to accept cv-qualified and ref-qualified types, which eliminates the need to prepare template argument types with metafunctions such as `std::remove_reference` and `std::decay`. This is especially useful when dealing with perfectly-forwarded parameter types in function templates. - -[*3.] [libname] is designed in terms of the [invoke] rules, with one unobtrusive and beneficial deviation: [concept_fn] types and [concept_abominable] types are compatible with all operations that do not specifically require an invocation. - -[*4.] [libns]`arg_at<2, Callable>` is both more flexible and more readable than `typename boost::function_traits::arg3_type`. - -[*5.] [libns]`can_invoke` can be used to test `INVOKE`-ability at compile-time, with value semantics. For the craziest metaprogrammers, [libns]`can_invoke_constexpr` does the same as `can_invoke` for [concept_constexpr_constructible] types, with an added check for `constexpr`-ness (Note: for `can_invoke_constexpr`, argument types must also be [concept_constexpr_constructible]) - -[*6.] [libns]`is_constexpr` can be used to check whether a [concept_constexpr_constructible] type is a [concept_callable] type that yields a `constexpr` result -- no arguments necessary. - -[*7.] [libns]`bind` can be used by library writers to easily accept `std::placeholder` expressions anywhere, and "intercept" the type information before forwarding to `std::bind` or `boost::bind`. This allows for more flexible APIs, where a function template taking a "callable type" can be overloaded to also accept placeholder expressions. It's perhaps a small improvement from requiring `std::bind` first, but in API design, even the smallest things count. See - -[*8.] [libns]`min_arity` can be used to detect the presence of default arguments on a [concept_simple_fn_obj] - -[*9.] The [libname] interface mainly consists of template aliases and `constexpr std::integral_constant` functions, which are arguably preferable to `typename foo::type` and `foo::value`. While the `std::integral_constant` functions in [libname] may be a deviation from traditional type trait designs, they facilitate a metaprogramming style that uses value-semantics (a la [hana]). The functions can generally be used with either types or values, which eliminates unnecessary `decltype` usage. - -[*10.] [libname] includes optional features for the manipulation and inspection of calling conventions. These features are currently deemed experimental, because they greatly increase the test surface of [libname], are platform-specific, and are not yet fully tested on any platform. +[section:ref_cc_tag [concept_cc_tag]] +* One of the following types, used to manipulate calling conventions programmatically: + *[namespace_scoped]`cdecl_tag` + *[namespace_scoped]`stdcall_tag` + *[namespace_scoped]`fastcall_tag` + *[namespace_scoped]`pascal_tag` [endsect] -[section:function_sugar Use case:[^ std::function] sugar] +[endsect][/section:concepts] -At the time of this writing, there are around 260 [@http://stackoverflow.com/search?q=convert+std%3A%3Abind+to+std%3A%3Afunction search results] on Stack Overflow concerning the conversion from `std::bind` to `std::function`. There are roughly 340 [@http://stackoverflow.com/search?q=convert+lambda+to+std%3A%3Afunction search results] concerning the conversion of lambdas to `std::function`. In the example below, we'll kill both birds with the same stone. The `make_function` function will leverage [libname] to... -# Create an `std::function` where T is not explicitly supplied by the user -# Create an `std::function` where T is the deduced "signature" of an `std::placeholders` expression. -Without real-world context, `make_function` may seem rather silly to those who know the runtime costs of type erasure. However, whenever `std::function` is required by some 3rd party API, this example might make a bit more sense. -[import ../example/make_function.cpp] -[make_function] - -[endsect] - -[endsect] - -[section:ref Reference] +[/*********************************************************************] +[/************************ H E A D E R S ******************************] +[/*********************************************************************] [section:headers Headers] The simplest way to use [libname] is to include the main header file: @@ -261,61 +442,74 @@ The simplest way to use [libname] is to include the main header file: [libname] interface is also broken down by trait into individual header files. To use only the traits you need, include one or more of the following headers, listed alphabetically: -[include_header [link callable_traits.ref_add_calling_convention add_calling_convention]] -[include_header [link callable_traits.ref_add_function_const add_function_const]] -[include_header [link callable_traits.ref_add_function_cv add_function_cv]] -[include_header [link callable_traits.ref_add_function_lvalue add_function_lvalue]] -[include_header [link callable_traits.ref_add_function_rvalue add_function_rvalue]] -[include_header [link callable_traits.ref_add_varargs add_varargs]] -[include_header [link callable_traits.ref_add_function_volatile add_function_volatile]] -[include_header [link callable_traits.ref_apply_member_pointer apply_member_pointer]] -[include_header [link callable_traits.ref_apply_return apply_return]] -[include_header [link callable_traits.ref_arg_at arg_at]] -[include_header [link callable_traits.ref_args args]] -[include_header [link callable_traits.ref_arity arity]] -[include_header [link callable_traits.ref_bind bind]] -[include_header [link callable_traits.ref_can_invoke can_invoke]] -[include_header [link callable_traits.ref_can_invoke_constexpr can_invoke_constexpr]] -[include_header [link callable_traits.ref_function_type function_type]] -[include_header [link callable_traits.ref_has_calling_convention has_calling_convention]] -[include_header [link callable_traits.ref_has_varargs has_varargs]] -[include_header [link callable_traits.ref_has_void_return has_void_return]] -[include_header [link callable_traits.ref_is_const_qualified is_const_qualified]] -[include_header [link callable_traits.ref_is_constexpr is_constexpr]] -[include_header [link callable_traits.ref_is_lvalue_qualified is_lvalue_qualified]] -[include_header [link callable_traits.ref_is_reference_qualified is_reference_qualified]] -[include_header [link callable_traits.ref_is_rvalue_qualified is_rvalue_qualified]] -[include_header [link callable_traits.ref_is_qualified is_qualified]] -[include_header [link callable_traits.ref_is_volatile_qualified is_volatile_qualified]] -[include_header [link callable_traits.ref_max_arity max_arity]] -[include_header [link callable_traits.ref_min_arity min_arity]] -[include_header [link callable_traits.ref_qualified_function_type qualified_function_type]] -[include_header [link callable_traits.ref_remove_calling_convention remove_calling_convention]] -[include_header [link callable_traits.ref_remove_function_const remove_function_const]] -[include_header [link callable_traits.ref_remove_function_cv remove_function_cv]] -[include_header [link callable_traits.ref_remove_member_pointer remove_member_pointer]] -[include_header [link callable_traits.ref_remove_function_reference remove_function_reference]] -[include_header [link callable_traits.ref_remove_varargs remove_varargs]] -[include_header [link callable_traits.ref_remove_function_volatile remove_function_volatile]] -[include_header [link callable_traits.ref_result_of result_of]] +* [include_header [link_add_calling_convention]] +* [include_header [link_add_function_const]] +* [include_header [link_add_function_cv]] +* [include_header [link_add_function_lvalue]] +* [include_header [link_add_function_rvalue]] +* [include_header [link_add_varargs]] +* [include_header [link_add_function_volatile]] +* [include_header [link_apply_member_pointer]] +* [include_header [link_apply_return]] +* [include_header [link_arg_at]] +* [include_header [link_args]] +* [include_header [link_arity]] +* [include_header [link_bind]] +* [include_header [link_can_invoke]] +* [include_header [link_can_invoke_constexpr]] +* [include_header [link_function_type]] +* [include_header [link_has_calling_convention]] +* [include_header [link_has_varargs]] +* [include_header [link_has_void_return]] +* [include_header [link_is_const_qualified]] +* [include_header [link_is_constexpr]] +* [include_header [link_is_lvalue_qualified]] +* [include_header [link_is_reference_qualified]] +* [include_header [link_is_rvalue_qualified]] +* [include_header [link_is_qualified]] +* [include_header [link_is_volatile_qualified]] +* [include_header [link_max_arity]] +* [include_header [link_min_arity]] +* [include_header [link_qualified_function_type]] +* [include_header [link_remove_calling_convention]] +* [include_header [link_remove_function_const]] +* [include_header [link_remove_function_cv]] +* [include_header [link_remove_member_pointer]] +* [include_header [link_remove_function_reference]] +* [include_header [link_remove_varargs]] +* [include_header [link_remove_function_volatile]] +* [include_header [link_result_of]] + +[endsect][/section:headers] + + +[template msvc_incompatible[] is not compatible with the Microsoft Visual C++ compiler in Visual Studio (a.k.a. MSVC). Accordingly, the example(s) below will not compile in MSVC. However, Windows users can still use clang-cl. Refer to the [link callable_traits.compatibility Compatibility page] for more information.] -[endsect] [section:ref_add_calling_convention add_calling_convention] -`add_calling_convention` will add a calling conventions to a pointer type, where `T` is a [concept_fn_ptr] or [concept_pmf], and `CcTag` is one of the following types: -*[libns]`cdecl_tag` -*[libns]`stdcall_tag` -*[libns]`fastcall_tag` -*[libns]`pascal_tag` + namespace ``[lib_namespace]`` { + + template + using add_calling_convention = /* implementation-defined */; + + } -For `add_calling_convention` to actually work, you must: +[heading Constraints] +* `T` must be a [link_fn_ptr] or [link_pmf] +* `CcTag` must be a [link_cc_tag] -# Be programming on a supported platform -# Add the calling convention to a pointer type where the platform allows you to do so -# Define the appropriate macro(s) before including: +[heading Behavior] +Adds the calling convention specified by `CcTag` to the pointer type `T`. + +[heading Notes] + +For `add_calling_convention` to work as-intended, you must: + +# Be programming on a platform that supports adding the desired calling convention to type `T` +# Define one or more of the following macros before including any [libname] headers: * `CALLABLE_TRAITS_ENABLE_CDECL` for `__cdecl` * `CALLABLE_TRAITS_ENABLE_STDCALL` for `__stdcall` * `CALLABLE_TRAITS_ENABLE_FASTCALL` for `__fastcall` @@ -329,70 +523,289 @@ For `add_calling_convention` to actually work, you must: [import ../example/experimental_calling_convention_cdecl.cpp] [experimental_calling_convention_cdecl] -[endsect] +[heading See Also] +* [link_remove_calling_convention] +* [link_has_calling_convention] + +[endsect][/section:ref_add_calling_convention] + + + + [section:ref_add_function_const add_function_const] -TODO + + namespace ``[lib_namespace]`` { + + template + using add_function_const = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be a [link_fn] or [link_pmf]. + +[heading Behavior] +Adds a `const` qualifier to the signature of `T`, if not already present. In other words, `int(foo::*)()` becomes `int(foo::*)() const`. + [heading Example] [import ../example/add_function_const.cpp] [add_function_const] -[endsect] + +[heading See Also] +* [link_remove_function_const] +* [link_is_const_qualified] + +[endsect][/section:ref_add_function_const] + + + + [section:ref_add_function_cv add_function_cv] -TODO + + namespace ``[lib_namespace]`` { + + template + using add_function_cv = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be a [link_fn] or [link_pmf]. + +[heading Behavior] +Adds both `const` and `volatile` qualifiers to the signature of `T`, if not already present. In other words, `int(foo::*)()` becomes `int(foo::*)() const volatile`. + [heading Example] [import ../example/add_function_cv.cpp] [add_function_cv] -[endsect] + +[heading See Also] +* [link_add_function_const] +* [link_add_function_volatile] +* [link_remove_function_cv] +* [link_is_cv_qualified] + +[endsect][/section:ref_add_function_cv] + + + + [section:ref_add_function_lvalue add_function_lvalue] -TODO + + namespace ``[lib_namespace]`` { + + template + using add_function_lvalue = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be a [link_fn] or [link_pmf]. + +[heading Behavior] +Adds an lvalue reference qualifier (`&`) to the signature of `T`, if not already present. In other words, `void(foo::*)()` becomes `void(foo::*)() &`. + [import ../example/add_function_lvalue.cpp] [add_function_lvalue] -[endsect] + +[heading See Also] +* [link_is_lvalue_qualified] +* [link_add_function_rvalue] +* [link_remove_function_reference] + +[endsect][/section:ref_add_function_lvalue] + + + [section:ref_add_function_rvalue add_function_rvalue] -TODO + + namespace ``[lib_namespace]`` { + + template + using add_function_rvalue = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be a [link_fn] or [link_pmf]. + +[heading Behavior] +Adds an rvalue reference qualifier (`&&`) to the signature of `T`, if not already present. In other words, `void(foo::*)()` becomes `void(foo::*)() &&`. + +[heading Example] [import ../example/add_function_rvalue.cpp] [add_function_rvalue] -[endsect] + +[heading See Also] +* [link_add_function_lvalue] +* [link_remove_function_reference] + +[endsect][/section:ref_add_function_rvalue] + + + + [section:ref_add_varargs add_varargs] -TODO + + namespace ``[lib_namespace]`` { + + template + using add_varargs = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be one of the following: +* [link_fn] +* [link_fn_ptr] +* [link_fn_ref] +* [link_pmf] + +[heading Behavior] +Adds C-style variadics (`...`) to the signature of `T`, if not already present. In other words, `int(int)` becomes `int(int, ...)`. + +[heading Example] [import ../example/add_varargs.cpp] [add_varargs] -[endsect] + +[heading See Also] +* [link_remove_varargs] +* [link_has_varargs] +* [link_remove_function_reference] + +[endsect][/section:ref_add_varargs] + + + + [section:ref_add_function_volatile add_function_volatile] -TODO -[endsect] + + namespace ``[lib_namespace]`` { + + template + using add_function_volatile = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be a [link_fn] or [link_pmf]. + +[heading Behavior] +Adds a `volatile` qualifier to the signature of `T`, if not already present. In other words, `void(foo::*)(char)` becomes `void(foo::*)(char) volatile`. + +[heading Example] +[import ../example/add_function_volatile.cpp] +[add_function_volatile] + +[heading See Also] +* [link_remove_function_volatile] +* [link_is_volatile_qualified] + +[endsect][/section:ref_add_function_volatile] + + + [section:ref_apply_member_pointer apply_member_pointer] -TODO + + namespace ``[lib_namespace]`` { + + template + using apply_member_pointer = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be one of the following: +* [link_fn] +* [link_fn_ptr] +* [link_fn_ref] +* [link_member_ptr] + +[heading Behavior] +When `T` is a [link_fn], [link_fn_ptr], or [link_fn_ref], the resulting type is a member function pointer of class/struct `Class`, with matching parameters and return type. When `T` is a [link_member_ptr], the resulting type is a member pointer of class/struct `Class`, pointing to the same type as the original [link_member_ptr]. + [heading Example] [import ../example/apply_member_pointer.cpp] [apply_member_pointer] -[endsect] + +[heading See Also] +* [link_remove_member_pointer] + +[endsect][/section:ref_apply_member_pointer] + + + + [section:ref_apply_return apply_return] -TODO + + namespace ``[lib_namespace]`` { + + template + using apply_return = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be one of the following: +* [link_fn] +* [link_fn_ptr] +* [link_fn_ref] +* [link_member_ptr] + +[heading Behavior] +When `T` is a [link_fn], [link_fn_ptr], [link_fn_ref], or [link_pmf], the resulting type's signature's return type will be of type `Return`, and the rest of the signature will be identical. When `T` is a [link_pmd], the resulting type points to a data member of type `Return`, with the same parent class as `T`. + [heading Example] [/import ../example/apply_return.cpp] [apply_return] -[endsect] + +[endsect][/section:ref_apply_return] + + + [section:ref_arg_at arg_at] -TODO + + namespace ``[lib_namespace]`` { + + template + using arg_at = /* implementation-defined */; + + } + +[heading Constraints] +`T` must be a [link_simple_callable]. `Index` must be less than `ArgCount` and greater than zero, where `ArgCount` is the number of arguments in the signature of `T` (the signature of `operator()` for [link_simple_fn_obj]). + +[heading Behavior] +When `Index` is outside the range defined above, the substitution fails in a SFINAE-friendly manner. Otherwise, the resulting type is the argument type at zero-based index `Index`. In other words, `arg_at<1, void(char, short, long)>` aliases `short`. + [heading Example] [/import ../example/arg_at.cpp] [arg_at] -[endsect] + +[heading See Also] +* [link_args] + +[endsect][/section:ref_arg_at] + + + + [section:ref_args args] TODO [heading Example] [import ../example/args.cpp] [args] + [endsect] [section:ref_arity arity] @@ -596,7 +1009,13 @@ TODO [result_of] [endsect] -[endsect] + + + +[/*********************************************************************] +[/************** A C K N O W L E D G E M E N T S **********************] +[/*********************************************************************] + [section:acknowledgements Acknowledgements] @@ -606,13 +1025,19 @@ Robert Ramey's CppCon 2014 presentation [@https://www.youtube.com/watch?v=ACeNgq Finally, I'd like to thank the faculty of the Harding University Computer Science Department for their mentorship and standards of excellence. -[endsect] +[endsect][/section:acknowledgements] + + + +[/*********************************************************************] +[/************************* C O N T A C T *****************************] +[/*********************************************************************] [section:contact Contact] [libname] is authored and maintained by Barrett Adair -Comments, feedback, and bug reports are ['highly] appreciated, and can be submitted in the following ways: +Comments, feedback, bug reports, and questions are appreciated, which can be submitted in the following ways: # Open a new issue [@https://github.com/badair/callable_traits/issues/new here] on GitHub # Message the author [@https://gitter.im/badair/callable_traits here] on Gitter, an excellent chat service built around GitHub, with message persistence and Markdown support @@ -620,7 +1045,7 @@ Comments, feedback, and bug reports are ['highly] appreciated, and can be submit * barrettellisadair * at... * gmail dot com - * (excuse the anti-spam measures) + * (please excuse the anti-spam formatting) -[endsect] +[endsect][/section:contact] diff --git a/doc/html/callable_traits/acknowledgements.html b/doc/html/callable_traits/acknowledgements.html index dd4bc32..641f236 100644 --- a/doc/html/callable_traits/acknowledgements.html +++ b/doc/html/callable_traits/acknowledgements.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
-PrevUpHomeNext +PrevUpHomeNext

@@ -53,7 +53,7 @@
-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/callable_traits/compatibility.html b/doc/html/callable_traits/compatibility.html new file mode 100644 index 0000000..10c1000 --- /dev/null +++ b/doc/html/callable_traits/compatibility.html @@ -0,0 +1,163 @@ + + + +Compatibility + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ CallableTraits is currently tested and working on the following + platforms, unless otherwise noted: +

+
+

Table 1. Supported Platforms

+
++++ + + + + + + + + + + + + + + + + + + +
+

+ Operating System +

+
+

+ Compilers +

+
+

+ Linux +

+
+

+ - Clang 3.5 and later (both libc++ and libstdc++) +

+

+ - GCC 5.2 and later +

+
+

+ OSX +

+
+

+ - Apple Clang in Xcode 6.3 and later +

+

+ - open-source Clang 3.5 and later should work, but is not yet tested +

+
+

+ Windows +

+
+

+ - Microsoft Visual Studio 2015 - Clang-cl +

+

+ - Microsoft Visual Studio 2015 - native MSVC - partial support (see + below) +

+

+ - MinGW GCC 5.3 (other versions not tested) +

+
+
+
+ + + + + +
[Note]Note
+

+ See the most recent cross-platform integration test results here + at Travis CI. Currently, Travis CI does not support Windows -- all Windows + testing is performed locally on the author's Windows 10 machine. +

+

+ CallableTraits has not been tested on every platform under the sun. If you + find CallableTraits to work with another toolchain, let + us know! +

+
+ +

+ While most of the features in CallableTraits are tested + and working in MSVC, the following 3 functions do not work: +

+
    +
  • + is_constexpr + - always returns an instance of std::false_type + in MSVC +
  • +
  • + can_invoke_constexpr + - always returns an instance of std::false_type + in MSVC +
  • +
  • + bind + - the aliased types inside the return type of this function are bugged. + A static_assert will trigger if this function is used in MSVC. +
  • +
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/concepts.html b/doc/html/callable_traits/concepts.html new file mode 100644 index 0000000..883a50c --- /dev/null +++ b/doc/html/callable_traits/concepts.html @@ -0,0 +1,332 @@ + + + +Concepts + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ + +

+ CallableTraits relies on the following concepts, which will + be cross-referenced throughout the documentation. Concepts will always be formatted + with green text. +

+
+ +
    +
  • + Any function pointer type +
  • +
  • + the pointer may be cv-qualified and/or ref-qualified +
  • +
  • + e.g. void(*)(int, int) or + void(* + const &)(int, int) +
  • +
+
+
+ +
    +
  • + Any function reference type +
  • +
  • + e.g. void(&)(int, int) +
  • +
+
+
+ +
    +
  • + Any unqualified function type +
  • +
  • + e.g. void(int, int) +
  • +
+
+
+ +
    +
  • + Any qualified (a.k.a. "abominable") + function type +
  • +
  • + Not technically "callable", but still falls under the CallableTraits + umbrella +
  • +
  • + Mutually exclusive with UnqualifiedFunction +
  • +
  • + e.g. void(int, int) const +
  • +
+
+
+ +
+
+
+ +
    +
  • + Any pointer to member function type +
  • +
  • + The pointer type may be cv-qualified and/or ref-qualified +
  • +
  • + e.g. void (foo::*)(int, int) +
  • +
+
+
+ +
    +
  • + Any pointer to data member type +
  • +
  • + The pointer type may be cv-qualified and/or ref-qualified +
  • +
  • + e.g. int foo::* +
  • +
+
+
+ +
+
+
+ +
    +
  • + Any class/struct with a non-templated, non-overloaded + function call operator +
  • +
  • + Includes non-generic lambda types +
  • +
  • + May be cv-qualified and/or ref-qualified. +
  • +
  • + Mutually exclusive with OverloadedFunctionObject +
  • +
  • + e.g. the type of this lambda: [](int x, int y) { return x + y; } +
  • +
+
+
+ +
    +
  • + Any class/struct with a templated or overloaded + function call operator, with the following limitation for those with + templated function call operators (which includes generic lambdas): +
    +
  • +
  • + May be cv-qualified and/or ref-qualified +
  • +
  • + e.g. the type of this generic lambda: [](auto x, auto y) { return x + y; } +
  • +
+
+ + + + + +
[Tip]Tip

+ Generic lambdas or classes with templated function objects that are either + not SFINAE-friendly or rely on dependent names for template instantiations + are generally incompatible with CallableTraits. +

+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
  • + Any LiteralType + that is also default-constructible +
+
+
+ +
  • + One of the following types, used to manipulate calling conventions programmatically: +
      +
    • + callable_traits::cdecl_tag +
    • +
    • + callable_traits::stdcall_tag +
    • +
    • + callable_traits::fastcall_tag +
    • +
    • + callable_traits::pascal_tag +
    • +
    +
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/contact.html b/doc/html/callable_traits/contact.html index 435732d..ebabae2 100644 --- a/doc/html/callable_traits/contact.html +++ b/doc/html/callable_traits/contact.html @@ -29,8 +29,8 @@ CallableTraits is authored and maintained by Barrett Adair

- Comments, feedback, and bug reports are highly appreciated, - and can be submitted in the following ways: + Comments, feedback, bug reports, and questions are appreciated, which can be + submitted in the following ways:

  1. @@ -55,7 +55,7 @@ gmail dot com
  2. - (excuse the anti-spam measures) + (please excuse the anti-spam formatting)
diff --git a/doc/html/callable_traits/function_sugar_example.html b/doc/html/callable_traits/function_sugar_example.html new file mode 100644 index 0000000..be38e23 --- /dev/null +++ b/doc/html/callable_traits/function_sugar_example.html @@ -0,0 +1,172 @@ + + + +Example:std::function sugar + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ At a glance, there appear to be around 260 search + results on Stack Overflow concerning the conversion from std::bind + to std::function, and around 340 search + results concerning the conversion of lambdas to std::function. + However misguided these questions might be, we'll kill both birds with the + same stone with the make_function + example below, which will leverage CallableTraits to... +

+
    +
  1. + Construct an std::function<T> + where T is not explicitly supplied by the user +
  2. +
  3. + Construct an std::function<T> + where T is the deduced "signature" of an std::placeholders + expression +
  4. +
+

+ Without real-world context, make_function + may seem rather silly, especially since we are needlessly incurring the runtime + cost of type erasure, which takes place inside the std::function + implementation. However, this make_function + might be useful in a situation where std::function + would be required by some 3rd party API. +

+
+ + + + + +
[Note]Note

+ Due to limitations in the Microsoft compiler, this example will not compile + with MSVC. For more information, refer to the MSVC + Issues section. +

+
#include <functional>
+#include <callable_traits/function_type.hpp>
+#include <callable_traits/bind.hpp>
+
+namespace example_library {
+
+    namespace ct = callable_traits;
+
+    // make_function turns a non-overloaded callable into a type-erased std::function object
+    template<typename T>
+    inline decltype(auto) make_function(T&& t) {
+
+        // callable_traits::function_type decays any non-overloaded callable type to
+        // a plain function type, which is structured in terms of INVOKE.
+
+        using signature = ct::function_type<T&&>;
+        using result_type = std::function<signature>;
+        return result_type{ std::forward<T>(t) };
+    }
+
+    // this make_function overload turns a bind expression into a type-erased std::function object
+    template<typename T, typename First, typename... Others>
+    inline decltype(auto) make_function(T&& t, First&& first, Others&&... others) {
+
+        // callable_traits::bind is essentially a compile-time parser of placeholder
+        // expressions, for the purpose of retaining more type information than
+        // std::bind normally allows - specifically, callable_traits::bind is used to
+        // determine the de-facto signature of the std::bind return type, with special
+        // considerations for conversions between reused placeholders and nested
+        // placeholder expressions. For the sake of convenience, callable_traits::bind
+        // is also a thin forwarding wrapper around std::bind (which is the only true
+        // runtime element in CallableTraits).
+
+        using bind_expr = decltype(ct::bind(
+                std::forward<T>(t),
+                std::forward<First>(first),
+                std::forward<Others>(others)...
+        ));
+
+        using signature = ct::function_type<bind_expr>;
+        using result_type = std::function<signature>;
+
+        return result_type{ std::bind(
+                std::forward<T>(t),
+                std::forward<First>(first),
+                std::forward<Others>(others)...
+        )};
+    }
+}
+
+// client code starts here
+#include <cassert>
+
+using namespace example_library;
+using namespace std::placeholders;
+
+int add(int i, int j) {
+    return i + j;
+}
+
+struct adder {
+
+    int eval(int i, int j) const {
+        return i + j;
+    }
+};
+
+int main() {
+
+    // function pointer
+    auto f = make_function(&add);
+    assert(f(99, 1) == 100);
+
+    // function reference
+    f = make_function(add);
+    assert(f(99, 1) == 100);
+
+    // member function pointer (bound to object)
+    f = make_function(&adder::eval, adder{}, _1, _2);
+    assert(f(99, 1) == 100);
+
+    // lambda
+    f = make_function([](int i, int j) {
+        return i + j;
+    });
+
+    assert(f(99, 1) == 100);
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/headers.html b/doc/html/callable_traits/headers.html new file mode 100644 index 0000000..9cfc9c4 --- /dev/null +++ b/doc/html/callable_traits/headers.html @@ -0,0 +1,168 @@ + + + +Headers + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ The simplest way to use CallableTraits is to include the + main header file: +

+

+ #include<callable_traits/callable_traits.hpp> +

+

+ CallableTraits interface is also broken down by trait into + individual header files. To use only the traits you need, include one or more + of the following headers, listed alphabetically: +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref.html b/doc/html/callable_traits/ref.html deleted file mode 100644 index 0900670..0000000 --- a/doc/html/callable_traits/ref.html +++ /dev/null @@ -1,1768 +0,0 @@ - - - -Reference - - - - - - - - - - - - - - - -
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
-
-
-PrevUpHomeNext -
-
- - -
- -

- The simplest way to use CallableTraits is to include the - main header file: -

-

- #include<callable_traits/callable_traits.hpp> -

-

- CallableTraits interface is also broken down by trait - into individual header files. To use only the traits you need, include one - or more of the following headers, listed alphabetically: -

-

- #include<callable_traits/add_calling_convention.hpp> - #include<callable_traits/add_function_const.hpp> - #include<callable_traits/add_function_cv.hpp> - #include<callable_traits/add_function_lvalue.hpp> - #include<callable_traits/add_function_rvalue.hpp> - #include<callable_traits/add_varargs.hpp> - #include<callable_traits/add_function_volatile.hpp> - #include<callable_traits/apply_member_pointer.hpp> - #include<callable_traits/apply_return.hpp> - #include<callable_traits/arg_at.hpp> - #include<callable_traits/args.hpp> - #include<callable_traits/arity.hpp> - #include<callable_traits/bind.hpp> - #include<callable_traits/can_invoke.hpp> - #include<callable_traits/can_invoke_constexpr.hpp> - #include<callable_traits/function_type.hpp> - #include<callable_traits/has_calling_convention.hpp> - #include<callable_traits/has_varargs.hpp> - #include<callable_traits/has_void_return.hpp> - #include<callable_traits/is_const_qualified.hpp> - #include<callable_traits/is_constexpr.hpp> - #include<callable_traits/is_lvalue_qualified.hpp> - #include<callable_traits/is_reference_qualified.hpp> - #include<callable_traits/is_rvalue_qualified.hpp> - #include<callable_traits/is_qualified.hpp> - #include<callable_traits/is_volatile_qualified.hpp> - #include<callable_traits/max_arity.hpp> - #include<callable_traits/min_arity.hpp> - #include<callable_traits/qualified_function_type.hpp> - #include<callable_traits/remove_calling_convention.hpp> - #include<callable_traits/remove_function_const.hpp> - #include<callable_traits/remove_function_cv.hpp> - #include<callable_traits/remove_member_pointer.hpp> - #include<callable_traits/remove_function_reference.hpp> - #include<callable_traits/remove_varargs.hpp> - #include<callable_traits/remove_function_volatile.hpp> - #include<callable_traits/result_of.hpp> -

-
-
- -

- add_calling_convention<T, CcTag> will add a calling conventions to a pointer - type, where T is a FunctionPtr or MemberFunctionPtr, - and CcTag is one of the following - types: -

-
    -
  • - callable_traits::cdecl_tag -
  • -
  • - callable_traits::stdcall_tag -
  • -
  • - callable_traits::fastcall_tag -
  • -
  • - callable_traits::pascal_tag -
  • -
-

- For add_calling_convention - to actually work, you must: -

-
    -
  1. - Be programming on a supported platform -
  2. -
  3. - Add the calling convention to a pointer type where the platform allows - you to do so -
  4. -
  5. - Define the appropriate macro(s) before including: -
      -
    • - CALLABLE_TRAITS_ENABLE_CDECL - for __cdecl -
    • -
    • - CALLABLE_TRAITS_ENABLE_STDCALL - for __stdcall -
    • -
    • - CALLABLE_TRAITS_ENABLE_FASTCALL - for __fastcall -
    • -
    • - CALLABLE_TRAITS_ENABLE_PASCAL - for pascal -
    • -
    -
  6. -
-
- - - - - -
[Warning]Warning

- This feature is currently considered experimental. Your feedback - is much appreciated! -

-
- - Example - - __fastcall to __stdcall -
-
#define CALLABLE_TRAITS_ENABLE_STDCALL
-#define CALLABLE_TRAITS_ENABLE_FASTCALL
-
-#include <type_traits>
-#include <callable_traits/has_calling_convention.hpp>
-#include <callable_traits/add_calling_convention.hpp>
-#include <callable_traits/remove_calling_convention.hpp>
-
-namespace ct = callable_traits;
-
-int main() {
-
-    using f = void(__fastcall *)(int);
-
-    static_assert(ct::has_calling_convention<f, ct::fastcall_tag>(), "");
-    static_assert(!ct::has_calling_convention<f, ct::stdcall_tag>(), "");
-
-    using expect = void(__stdcall *)(int);
-
-    static_assert(ct::has_calling_convention<expect, ct::stdcall_tag>(), "");
-    static_assert(!ct::has_calling_convention<expect, ct::fastcall_tag>(), "");
-
-    using g = ct::remove_calling_convention<f>;
-    using test = ct::add_calling_convention<g, ct::stdcall_tag>;
-
-    static_assert(ct::has_calling_convention<test, ct::stdcall_tag>(), "");
-    static_assert(std::is_same<test, expect>::value, "");
-}
-
-
- - Example - - __cdecl -
-
#define CALLABLE_TRAITS_ENABLE_CDECL
-
-#include <type_traits>
-#include <callable_traits/has_calling_convention.hpp>
-#include <callable_traits/add_calling_convention.hpp>
-
-namespace ct = callable_traits;
-
-struct foo {};
-
-int main() {
-
-    //depending on your platform, pmf may already have an implicit __cdecl
-    using pmf = void(foo::*)();
-    using expect = void(__cdecl foo::*)();
-    using test = ct::add_calling_convention<pmf, ct::cdecl_tag>;
-
-    static_assert(std::is_same<test, expect>::value, "");
-    static_assert(ct::has_calling_convention<expect, ct::cdecl_tag>(), "");
-    static_assert(ct::has_calling_convention<test, ct::cdecl_tag>(), "");
-}
-
-
-
- -

- TODO -

-
- - Example -
-
#include <type_traits>
-#include <callable_traits/add_function_const.hpp>
-
-namespace ct = callable_traits;
-
-struct foo {};
-
-int main() {
-
-    {
-        using pmf = void(foo::*)();
-        using expect = void(foo::*)() const;
-        using test = ct::add_function_const<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_const doesn't change anything when
-        // the function type is already const.
-        using pmf = void(foo::*)() const &&;
-        using expect = void(foo::*)() const &&;
-        using test = ct::add_function_const<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        using pmf = void(foo::*)() volatile &;
-        using expect = void(foo::*)() const volatile &;
-        using test = ct::add_function_const<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_const can also be used with "abominable"
-        // function types.
-        using f = void();
-        using expect = void() const;
-        using test = ct::add_function_const<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_const does not compile with function pointers,
-        // function references, function objects, or member data pointers.
-        // However, you can loosen this restriction somewhat by using the
-        // callable_traits::permissive namespace instead:
-        using f = void(*)();
-        using expect = f;
-        using test = ct::permissive::add_function_const<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-}
-
-
-
- -

- TODO -

-
- - Example -
-
#include <type_traits>
-#include <callable_traits/add_function_cv.hpp>
-
-namespace ct = callable_traits;
-
-struct foo {};
-
-int main() {
-
-    {
-        using pmf = void(foo::*)();
-        using expect = void(foo::*)() const volatile;
-        using test = ct::add_function_cv<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_cv doesn't change anything when
-        // the function type is already cv-qualified.
-        using pmf = void(foo::*)() const volatile &&;
-        using expect = void(foo::*)() const volatile &&;
-        using test = ct::add_function_cv<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        using pmf = void(foo::*)() volatile &;
-        using expect = void(foo::*)() const volatile &;
-        using test = ct::add_function_cv<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_cv can also be used with "abominable"
-        // function types.
-        using f = void();
-        using expect = void() const volatile;
-        using test = ct::add_function_cv<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_cv does not compile with function pointers,
-        // function references, function objects, or member data pointers.
-        // However, you can loosen this restriction somewhat by using the
-        // callable_traits::permissive namespace instead:
-        using f = void(*)();
-        using expect = f;
-        using test = ct::permissive::add_function_cv<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-}
-
-
-
- -

- TODO -

-
#include <type_traits>
-#include <callable_traits/add_function_lvalue.hpp>
-
-namespace ct = callable_traits;
-
-struct foo {};
-
-int main() {
-
-    {
-        using pmf = void(foo::*)();
-        using expect = void(foo::*)() &;
-        using test = ct::add_function_lvalue<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_lvalue doesn't change anything when
-        // the function type already has an lvalue qualifier.
-        using pmf = void(foo::*)() &;
-        using expect = void(foo::*)() &;
-        using test = ct::add_function_lvalue<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_lvalue models C++11 reference collapsing
-        // rules, so that adding an lvalue qualifier to an
-        // rvalue-qualified type will force the lvalue.
-        using pmf = void(foo::*)() &&;
-        using expect = void(foo::*)() &;
-        using test = ct::add_function_lvalue<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_lvalue can also be used to create "abominable"
-        // function types.
-        using f = void();
-        using expect = void() &;
-        using test = ct::add_function_lvalue<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_lvalue does not compile with function pointers,
-        // function references, function objects, or member data pointers.
-        // However, you can loosen this restriction somewhat by using the
-        // callable_traits::permissive namespace instead:
-        using f = void(*)();
-        using expect = f;
-        using test = ct::permissive::add_function_lvalue<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-}
-
-
-
- -

- TODO -

-
#include <type_traits>
-#include <callable_traits/add_function_rvalue.hpp>
-
-namespace ct = callable_traits;
-
-struct foo {};
-
-int main() {
-
-    {
-        using pmf = void(foo::*)();
-        using expect = void(foo::*)() &&;
-        using test = ct::add_function_rvalue<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_rvalue doesn't change anything when
-        // the function type already has an rvalue qualifier.
-        using pmf = void(foo::*)() &&;
-        using expect = void(foo::*)() &&;
-        using test = ct::add_function_rvalue<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_rvalue models C++11 reference collapsing
-        // rules, so that adding an rvalue qualifier to an
-        // lvalue-qualified type will not change anything.
-        using pmf = void(foo::*)() const &;
-        using expect = void(foo::*)() const &;
-        using test = ct::add_function_rvalue<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_rvalue can also be used with "abominable"
-        // function types.
-        using f = void() const;
-        using expect = void() const &&;
-        using test = ct::add_function_rvalue<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        // add_function_rvalue does not compile with function pointers,
-        // function references, function objects, or member data pointers.
-        // However, you can loosen this restriction somewhat by using the
-        // callable_traits::permissive namespace instead:
-        using f = void(*)();
-        using expect = f;
-        using test = ct::permissive::add_function_rvalue<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-}
-
-
-
- -

- TODO -

-
#include <type_traits>
-#include <callable_traits/add_varargs.hpp>
-
-namespace ct = callable_traits;
-
-struct foo {};
-
-int main() {
-
-    {
-        using f = void(int);
-        using expect = void(int, ...);
-        using test = ct::add_varargs<f>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        using fp = void(*)();
-        using expect = void(*)(...);
-        using test = ct::add_varargs<fp>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        using fr = void(&)(const char*);
-        using expect = void(&)(const char*, ...);
-        using test = ct::add_varargs<fr>;
-        static_assert(std::is_same<test, expect>::value, "");
-    } {
-        using pmf = void(foo::*)() const;
-        using expect = void(foo::*)(...) const;
-        using test = ct::add_varargs<pmf>;
-        static_assert(std::is_same<test, expect>::value, "");
-
-        // add_varargs doesn't change anything when
-        // the type already has varargs.
-        using twice = ct::add_varargs<test>;
-        static_assert(std::is_same<test, twice>::value, "");
-    }
-
-    // add_varargs fails in a SFINAE-friendly manner when
-    // used on a function object or a member data pointer.
-    //
-    // {
-    //     using d = int foo::*;
-    //     using test = ct::add_varargs<d>;
-    // }
-    //
-    // The error message is about as obvious as it can be without
-    // resorting to a SFINAE-unfriendly static_assert (namespaces
-    // omitted for brevity):
-    //
-    //   error: no type named 'type' in 'struct disjunction<
-    //   type_value<invalid_type, false>, add_varargs_error<0> >'
-}
-
-
-
- -

- TODO -

-
-
- -

- TODO -

-
- - Example -
-
#include <type_traits>
-#include <callable_traits/apply_member_pointer.hpp>
-
-namespace ct = callable_traits;
-
-struct foo;
-struct bar;
-
-using expect = int(foo::*)(int);
-
-int main() {
-
-    {
-        using f = int(int);
-        using test = ct::apply_member_pointer<f, foo>;
-        using expect = int(foo::*)(int);
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-
-    {
-        using f = int(* const &)(int);
-        using test = ct::apply_member_pointer<f, foo>;
-        using expect = int(foo::* const &)(int);
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-
-    {
-        using f = int(&)(int);
-        using test = ct::apply_member_pointer<f, foo>;
-        using expect = int(foo::*)(int);
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-
-    {
-        using f = int(foo::*)(int);
-        using test = ct::apply_member_pointer<f, foo>;
-        using expect = int(foo::*)(int);
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-
-    {
-        using f = int(bar::* const)(int);
-        using test = ct::apply_member_pointer<f, foo>;
-        using expect = int(foo::* const)(int);
-        static_assert(std::is_same<test, expect>::value, "");
-    }
-}
-
-
-
- -

- TODO -

-
- - Example -
-

- [apply_return] -

-
-
-

-arg_at -

-

- TODO -

-
- - Example -
-

- [arg_at] -

-
-
-

-args -

-

- TODO -

-
- - Example -
-
#include <type_traits>
-#include <memory>
-#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-// all callable types in this example use these parameter types
-using expect = std::tuple<int, float&, const char*>;
-
-template<typename T>
-void test(){
-    // this example shows how callable_traits::args
-    // bevaves consistently for many different types
-    using args = ct::args<T>;
-    static_assert(std::is_same<expect, args>{}, "");
-}
-
-int main() {
-
-
-    auto lamda = [](int, float&, const char*){};
-    using lam = decltype(lamda);
-    test<lam>();
-    test<lam&>();
-    test<lam&&>();
-    test<lam const &>();
-
-    struct foo;
-    using pmf = void(foo::*)(int, float&, const char*);
-    test<pmf>();
-    test<pmf&>();
-    test<pmf&&>();
-    test<pmf const &>();
-
-    using function_ptr = void(*)(int, float&, const char*);
-    test<function_ptr>();
-    test<function_ptr&>();
-    test<function_ptr&&>();
-    test<function_ptr const &>();
-
-    using function_ref = void(&)(int, float&, const char*);
-    test<function_ref>();
-
-    using function = void(int, float&, const char*);
-    test<function>();
-
-    using abominable = void(int, float&, const char*) const;
-    test<abominable>();
-}
-
-
-
-

-arity -

-

- TODO -

-
- - Example -
-

- [arity] -

-
-
-

-bind -

-

- TODO -

-
- - Example - 1 -
-
/* In this example, the last _1 placeholder in the bind
-expression forces all other _1 slots to accept ScaryMonster,
-because ScaryMonster is the narrowest of all _1 parameters. */
-
-#include <cassert>
-#include <type_traits>
-#include <functional>
-#include <tuple>
-#include <callable_traits/callable_traits.hpp>
-
-struct Vampire {};
-struct Robot {};
-struct Animal {};
-struct Dog : Animal {};
-struct Poodle : Dog {};
-struct ScaryMonster : Vampire, Robot, Poodle {};
-
-auto vampire_to_robot(Vampire) {
-    return Robot{};
-}
-
-auto robot_to_dog = [](Robot){
-    return Dog{};
-};
-
-struct converter {
-    auto dog_to_vampire(Dog) {
-        return Vampire{};
-    }
-};
-
-int take_all(Vampire, Robot, Animal, Dog, Poodle, ScaryMonster) {
-    return 0;
-}
-
-using namespace std::placeholders;
-namespace ct = callable_traits;
-
-int main() {
-
-    auto b =
-        ct::bind(&take_all,
-            ct::bind(&converter::dog_to_vampire,
-                converter{},
-                ct::bind(robot_to_dog,
-                    ct::bind(&vampire_to_robot, _1)
-                )
-            ),
-            ct::bind(&vampire_to_robot, _3),
-            Animal{},
-            _1,
-            _2,
-            _1
-        );
-
-    {
-        using args = ct::args<decltype(b)>;
-        using expect = std::tuple<ScaryMonster, Poodle, Vampire>;
-        static_assert(std::is_same<args, expect>::value, "");
-    } {
-        using type = ct::function_type<decltype(b)>;
-        using expect = int(ScaryMonster, Poodle, Vampire);
-        static_assert(std::is_same<type, expect>::value, "");
-    }
-
-    assert(b(ScaryMonster{}, Poodle{}, Vampire{}) == 0);
-
-    return 0;
-}
-
-
- - Example - 2 -
-
#include <cassert>
-#include <type_traits>
-#include <functional>
-#include <tuple>
-#include <callable_traits/callable_traits.hpp>
-
-struct Vampire {};
-struct Robot {};
-struct Animal {};
-struct Dog : Animal {};
-struct Poodle : Dog {};
-struct ScaryMonster : Poodle, Robot, Vampire {};
-
-auto take_vampire(const Vampire&) { return 0; }
-auto take_robot(const Robot&) { return 0; }
-auto take_dog(const Dog&) { return 0; }
-auto take_scary_monster(const ScaryMonster&) { return 0; }
-
-int f(int, int, int, int) { return 0; }
-
-using namespace std::placeholders;
-namespace ct = callable_traits;
-
-int main() {
-
-    ScaryMonster monster{};
-
-    auto b = ct::bind(
-        &f,
-        ct::bind(&take_vampire, _1),
-        ct::bind(&take_robot, _1),
-        ct::bind(&take_dog, _1),
-        ct::bind(&take_scary_monster, _1)
-    );
-
-    {
-        using args = ct::args<decltype(b)>;
-        using expect = std::tuple<const ScaryMonster&>;
-        static_assert(std::is_same<args, expect>::value, "");
-    } {
-        using type = ct::function_type<decltype(b)>;
-        using expect = int(const ScaryMonster&);
-        static_assert(std::is_same<type, expect>::value, "");
-    }
-
-    assert(b(monster) == 0);
-
-    return 0;
-}
-
-
-
- -

- TODO -

-
- - Example - - Function Object -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-// For the purpose of this example, 'Bad' represents
-// any non-arithmetic type
-struct Bad {};
-Bad bad{};
-
-// non-generic callables, such as `subtract` below,
-// don't have any "gotchas" when passed to
-// callable_traits::can_invoke.
-auto subtract = [](int x, int y) {
-    return x + y;
-};
-
-static_assert(!ct::can_invoke(subtract), "");
-static_assert(!ct::can_invoke(subtract, 1), "");
-static_assert(ct::can_invoke(subtract, 1, 2), ""); // <-- success
-static_assert(!ct::can_invoke(subtract, 1, 2, 3), "");
-static_assert(!ct::can_invoke(subtract, bad, bad), "");
-
-// Generic function objects (such as `add` and `multiply` below)
-// must be SFINAE-friendly in order for failing can_invoke calls
-// to actually compile. This applies to both generic lambdas and
-// templated function objects. Note: MSVC does not compile this
-// source code file because of the trailing return type below (MSVC
-// is non-conforming in this respect)
-
-auto add = [](auto x, auto y) -> decltype(x + y) {
-    return x + y;          // ^^^^^^^^^^^^^^^^^^ explicit return type allows SFINAE
-};
-
-template<int I>
-using int_c = std::integral_constant<int, I>;
-
-static_assert(!ct::can_invoke(add), "");
-static_assert(!ct::can_invoke(add, 1), "");
-static_assert(ct::can_invoke(add, 1, 2), ""); // <-- success
-static_assert(!ct::can_invoke(add, 1, 2, 3), "");
-static_assert(!ct::can_invoke(add, bad, bad), "");
-
-// 'multiply' isn't SFINAE-safe, because the return type depends
-// on an expression in the body. However, it still works if we
-// only try to call can_invoke with arguments where x * y is
-// a valid expression.
-auto multiply = [](auto x, auto y) {
-    return x * y;
-};
-
-
-static_assert(!ct::can_invoke(multiply), "");
-static_assert(!ct::can_invoke(multiply, 1), "");
-static_assert(ct::can_invoke(multiply, 1, 2), ""); // <-- success
-static_assert(!ct::can_invoke(multiply, 1, 2, 3), "");
-//static_assert(!ct::can_invoke(multiply, bad, bad), "");
-
-// The last, commented static_assert above would fail compile,
-// because the call cannot be SFINAE'd away. Error message in Clang:
-// "invalid operands to binary expression ('Bad' and 'Bad')"
-
-int main() {}
-
-
- - Example - - Member Function Pointer -
-
#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-struct foo {
-    int bar(int) const {
-        return 1;
-    }
-};
-
-// can_invoke returns std::true_type here because the
-// arguments are valid to INVOKE
-static_assert(ct::can_invoke(&foo::bar, foo{}, 0), "");
-
-// can_invoke returns std::false_type here because the
-// arguments are NOT valid to INVOKE - foo::bar can't be
-// invoked like a void member function.
-static_assert(!ct::can_invoke(&foo::bar, foo{}), "");
-
-int main() {}
-
-
- - Example - - Function Pointer -
-
#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-int foo(int&& i) {
-    return i;
-}
-
-// can_invoke returns std::true_type here because the
-// arguments are valid to INVOKE
-static_assert(ct::can_invoke(&foo, 0), "");
-
-int i = 0;
-
-// can_invoke returns std::false_type here because the
-// arguments are NOT valid to INVOKE - foo expects an
-// rvalue reference, not an lvalue reference.
-static_assert(!ct::can_invoke(&foo, i), "");
-
-int main() {}
-
-
- - Example - - Function Reference -
-
#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-int foo(int&& i) {
-    return i;
-}
-
-// can_invoke returns std::true_type here because the
-// arguments are valid to INVOKE
-static_assert(ct::can_invoke(foo, 0), "");
-
-int i = 0;
-
-// can_invoke returns std::false_type here because the
-// arguments are NOT valid to INVOKE - foo expects an
-// rvalue reference, not an lvalue reference.
-static_assert(!ct::can_invoke(foo, i), "");
-
-int main() {}
-
-
-
- -

- TODO -

-
- - Example - - Function Object -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-// NOTE: Due to non-compliance in MSVC, can_invoke_constexpr
-// always return std::false_type on that compiler, which causes
-// the static asserts below to fail.
-
-namespace ct = callable_traits;
-
-using T1 = std::integral_constant<int, 3>;
-using T2 = std::integral_constant<int, 7>;
-
-//'subtract' is a constexpr function object that
-// subtracts std::integral_constant types.
-struct subtract {
-
-    // To compile failing cases of can_invoke_constexpr, the function object
-    // must have a SFINAE-safe signature. In this case, 'subtract' is made
-    // SFINAE-safe with an explicit, trailing return type.
-    template<typename T1, typename T2>
-    constexpr auto operator()(T1, T2) const -> decltype(T1::value - T2::value) {
-        return T1::value - T2::value;
-    }
-};
-
-// can_invoke_constexpr returns std::true_type in the first case, because
-// INVOKE(subtract{}, T1{}, T2{}) is a valid expression, AND 'subtract{}' is
-// a constexpr function object.
-static_assert(ct::can_invoke_constexpr(subtract{}, T1{}, T2{}), "");
-static_assert(!ct::can_invoke_constexpr(subtract{}, 3, 7), "");
-static_assert(!ct::can_invoke_constexpr(subtract{}, T1{}), "");
-
-//this is a function object, but is NOT constexpr
-struct add {
-    template<typename T1, typename T2>
-    auto operator()(T1, T2) const -> decltype(T1::value + T2::value) {
-        return T1::value + T2::value;
-    }
-};
-
-// Even though INVOKE(add{}, T1{}, T2{}) is valid, the respective
-// can_invoke_constexpr call returns std::false_type because 'add{}'
-// is not a constexpr function object.
-static_assert(!ct::can_invoke_constexpr(add{}, T1{}, T2{}), "");
-static_assert(!ct::can_invoke_constexpr(add{}, 3, 7), "");
-
-
-// This last section demonstrates that can_invoke_constexpr will always
-// return std::false_type when any of the arguments do not decay to literal
-// types. (see http://en.cppreference.com/w/cpp/concept/LiteralType).
-// Even though 'S' below is a constexpr function object, it is incompatible
-// with can_invoke_constexpr because 'S' isn't a literal type. Additionally,
-// all arguments must be default constructible.
-
-struct S {
-    S() = delete;
-    S(int){};
-    constexpr int operator()() const { return 0; }
-};
-
-S s{0};
-static_assert(!ct::can_invoke_constexpr(s), "");
-
-
-int main() {}
-
-
- - Example - - Member Function Pointer -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-// NOTE: Due to non-compliance in MSVC, can_invoke_constexpr
-// always returns std::false_type on that compiler, which
-// causes a static assert below to fail.
-
-namespace ct = callable_traits;
-
-struct foo {
-    constexpr int bar(int) const {
-        return 1;
-    }
-};
-
-using pmf_constant = std::integral_constant<decltype(&foo::bar), &foo::bar>;
-
-// can_invoke_constexpr returns true here because foo::bar
-// is constexpr, and the arguments are valid to INVOKE
-static_assert(ct::can_invoke_constexpr(pmf_constant{}, foo{}, 0), "");
-
-// can_invoke_constexpr returns false here because even though
-// foo::bar is constexpr, the arguments do not obey INVOKE rules
-static_assert(!ct::can_invoke_constexpr(pmf_constant{}, foo{}), "");
-
-int main() {}
-
-
- - Example - - Function Pointer -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-constexpr int seven(int) {
-    return 7;
-}
-
-using seven_c = std::integral_constant<decltype(&seven), &seven>;
-
-// The first call to can_invoke_constexpr returns std::true_type
-// because `seven` is a constexpr function, and valid INVOKE arguments
-// are passed. The second call to can_invoke_constexpr returns
-// std::false_type, because the arguments are not valid to INVOKE
-static_assert(ct::can_invoke_constexpr(seven_c{}, 0), "");
-static_assert(!ct::can_invoke_constexpr(seven_c{}, nullptr), "");
-
-int eight(int) {
-    return 7;
-}
-
-using eight_c = std::integral_constant<decltype(&eight), &eight>;
-
-// `eight` is NOT a constexpr function, so can_invoke_constexpr
-// returns `std::false_type` even for valid INVOKE arguments.
-static_assert(!ct::can_invoke_constexpr(eight_c{}, 0), "");
-static_assert(!ct::can_invoke_constexpr(eight_c{}, nullptr), "");
-
-int main() {}
-
-
-
- -

- TODO -

-
- - Example -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-template<typename T>
-void test(){
-
-    // this example shows how callable_traits::function_type
-    // bevaves consistently for many different types
-    using type = ct::function_type<T>;
-    using expect = void(int, float&, const char*);
-    static_assert(std::is_same<expect, type>{}, "");
-}
-
-int main() {
-
-    auto lamda = [](int, float&, const char*){};
-    using lam = decltype(lamda);
-    test<lam>();
-    test<lam&>();
-    test<lam&&>();
-    test<lam const &>();
-
-    using function_ptr = void(*)(int, float&, const char*);
-    test<function_ptr>();
-    test<function_ptr&>();
-    test<function_ptr&&>();
-    test<function_ptr const &>();
-
-    using function_ref = void(&)(int, float&, const char*);
-    test<function_ref>();
-
-    using function = void(int, float&, const char*);
-    test<function>();
-
-    using abominable = void(int, float&, const char*) const;
-    test<abominable>();
-}
-
-
-
- -

- TODO -

-
- - Example - - __fastcall to __stdcall -
-
#define CALLABLE_TRAITS_ENABLE_STDCALL
-#define CALLABLE_TRAITS_ENABLE_FASTCALL
-
-#include <type_traits>
-#include <callable_traits/has_calling_convention.hpp>
-#include <callable_traits/add_calling_convention.hpp>
-#include <callable_traits/remove_calling_convention.hpp>
-
-namespace ct = callable_traits;
-
-int main() {
-
-    using f = void(__fastcall *)(int);
-
-    static_assert(ct::has_calling_convention<f, ct::fastcall_tag>(), "");
-    static_assert(!ct::has_calling_convention<f, ct::stdcall_tag>(), "");
-
-    using expect = void(__stdcall *)(int);
-
-    static_assert(ct::has_calling_convention<expect, ct::stdcall_tag>(), "");
-    static_assert(!ct::has_calling_convention<expect, ct::fastcall_tag>(), "");
-
-    using g = ct::remove_calling_convention<f>;
-    using test = ct::add_calling_convention<g, ct::stdcall_tag>;
-
-    static_assert(ct::has_calling_convention<test, ct::stdcall_tag>(), "");
-    static_assert(std::is_same<test, expect>::value, "");
-}
-
-
-
- -

- TODO -

-
- - Example -
-

- [has_varargs] -

-
-
- -

- TODO -

-
- - Example -
-

- [has_void_return] -

-
-
- -

- TODO -

-
- - Example -
-

- [is_const_qualified] -

-
-
- -

- TODO -

-
- - Example - - Function Object -
-
- - - - - -
[Warning]Warning

- When compiling in MSVC, is_constexpr - always returns std::false_type, because MSVC cannot compile - the logic that normally determines this. -

-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-//this is a constexpr function object (non-templated)
-struct zero {
-
-    constexpr auto operator()() const {
-        return 0;
-    }
-};
-
-static_assert(ct::is_constexpr<zero>(), "");
-static_assert(ct::is_constexpr(zero{}), "");
-
-
-
-//this is a constexpr function object (templated)
-struct subtract {
-
-    // For callable_traits::is_constexpr, generic function objects
-    // only need to be SFINAE-friendly if the body of the operator()
-    // function accesses member names besides "type" and "value".
-    // Unary/binary operators and constructor calls are okay to use.
-    template<typename T1, typename T2>
-    constexpr auto operator()(T1, T2) const {
-        return T1{} - T2{};
-    }
-};
-
-static_assert(ct::is_constexpr<subtract>(), "");
-static_assert(ct::is_constexpr(subtract{}), "");
-
-
-
-//this is NOT a constexpr function object
-struct add {
-    template<typename T1, typename T2>
-    auto operator()(T1, T2) const {
-        return T1{} + T2{};
-    }
-};
-
-static_assert(!ct::is_constexpr<add>(), "");
-static_assert(!ct::is_constexpr(add{}), "");
-
-auto multiply = [](auto t1, auto t2) -> decltype(t1.value * t2.value) {
-    return t1.value * t2.value;
-};
-
-static_assert(!ct::is_constexpr<decltype(multiply)>(), "");
-static_assert(!ct::is_constexpr(multiply), "");
-
-
-// is_constexpr will always return std::false_type when the argument
-// is either not a literal type, or is not default constructible. Below,
-// divide is not default constructible, so is_constexpr returns
-// std::false_type. For literal types that are default constructible, a
-// constexpr default constructor is assumed.
-
-struct divide {
-
-    divide() = delete;
-    constexpr divide(int){};
-
-    template<typename T1, typename T2>
-    constexpr auto operator()(T1, T2) const {
-        return T1{} / T2{};
-    }
-};
-
-static_assert(!ct::is_constexpr<divide>(), "");
-static_assert(!ct::is_constexpr(divide{0}), "");
-
-int main() {}
-
-
- - Example - - Function Pointer -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-// NOTE: Due to non-compliance in MSVC, is_constexpr always
-// returns std::false_type on that compiler, which causes
-// the static asserts below to fail.
-
-namespace ct = callable_traits;
-
-constexpr int foo(const int&) {
-    return 1;
-}
-
-int bar(const int&) {
-    return 1;
-}
-
-// for is_constexpr calls, function pointers must
-// be passed as std::integral_constants
-using F = std::integral_constant<decltype(&foo), &foo>;
-using B = std::integral_constant<decltype(&bar), &bar>;
-
-static_assert(ct::is_constexpr(F{}), "");
-static_assert(ct::is_constexpr<F>(), "");
-static_assert(!ct::is_constexpr(B{}), "");
-static_assert(!ct::is_constexpr<B>(), "");
-
-int main() {}
-
-
-
- -

- TODO -

-
- - Example -
-

- [is_lvalue_qualified] -

-
-
- -

- TODO -

-
- - Example -
-

- [is_reference_qualified] -

-
-
- -

- TODO -

-
- - Example -
-

- [is_rvalue_qualified] -

-
-
- -

- TODO -

-
- - Example -
-

- [is_qualified] -

-
-
- -

- TODO -

-
- - Example -
-

- [is_volatile_qualified] -

-
-
- -

- TODO -

-
- - Example -
-

- [max_arity] -

-
-
- -

- TODO -

-
- - Example -
-

- [min_arity] -

-
-
- -

- TODO -

-
- - Example -
-

- [qualified_function_type] -

-
-
- -

- TODO -

-
- - Example - - __fastcall to __stdcall -
-
#define CALLABLE_TRAITS_ENABLE_STDCALL
-#define CALLABLE_TRAITS_ENABLE_FASTCALL
-
-#include <type_traits>
-#include <callable_traits/has_calling_convention.hpp>
-#include <callable_traits/add_calling_convention.hpp>
-#include <callable_traits/remove_calling_convention.hpp>
-
-namespace ct = callable_traits;
-
-int main() {
-
-    using f = void(__fastcall *)(int);
-
-    static_assert(ct::has_calling_convention<f, ct::fastcall_tag>(), "");
-    static_assert(!ct::has_calling_convention<f, ct::stdcall_tag>(), "");
-
-    using expect = void(__stdcall *)(int);
-
-    static_assert(ct::has_calling_convention<expect, ct::stdcall_tag>(), "");
-    static_assert(!ct::has_calling_convention<expect, ct::fastcall_tag>(), "");
-
-    using g = ct::remove_calling_convention<f>;
-    using test = ct::add_calling_convention<g, ct::stdcall_tag>;
-
-    static_assert(ct::has_calling_convention<test, ct::stdcall_tag>(), "");
-    static_assert(std::is_same<test, expect>::value, "");
-}
-
-
-
- -

- TODO -

-
- - Example -
-

- [remove_function_const] -

-
-
- -

- TODO -

-
- - Example -
-

- [remove_function_cv] -

-
-
- -

- TODO -

-
- - Example -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-struct foo;
-
-template<typename T, typename Expect>
-void test() {
-    using U = ct::remove_member_pointer<T>;
-    static_assert(std::is_same<Expect, U>{}, "");
-}
-
-int main() {
-
-    {
-        using T = int(foo::*)(int) const;
-        using expect = int(int) const;
-        test<T, expect>();
-    } {
-        using T = int foo::*;
-        using expect = int;
-        test<T, expect>();
-    } {
-        using T = int(int);
-        test<T, T>();
-    } {
-        using T = int(*)(int);
-        test<T, T>();
-    } {
-        using T = int(&)(int);
-        test<T, T>();
-    }
-}
-
-
-
- -

- TODO -

-
- - Example -
-

- [remove_function_reference] -

-
-
- -

- TODO -

-
- - Example -
-

- [remove_varargs] -

-
-
- -

- TODO -

-
- - Example -
-

- [remove_function_volatile] -

-
-
- -

- TODO -

-
- - Example -
-
#include <type_traits>
-#include <callable_traits/callable_traits.hpp>
-
-namespace ct = callable_traits;
-
-using expect = int;
-
-struct foo;
-
-template<typename T>
-void test() {
-    using result = ct::result_of<T>;
-    static_assert(std::is_same<expect, result>{}, "");
-}
-
-int main() {
-
-    test<int()>();
-    test<int(*)()>();
-    test<int(&)()>();
-    test<int() const>();
-    test<int(foo::*)() const>();
-
-    auto x = []() -> int { return 0; };
-
-    test<decltype(x)>();
-}
-
-
-
- - - -
-
-
-PrevUpHomeNext -
- - diff --git a/doc/html/callable_traits/ref_add_calling_convention.html b/doc/html/callable_traits/ref_add_calling_convention.html new file mode 100644 index 0000000..276d0b9 --- /dev/null +++ b/doc/html/callable_traits/ref_add_calling_convention.html @@ -0,0 +1,190 @@ + + + +add_calling_convention + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T, typename CcTag>
+    using add_calling_convention = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+
+

+ + Behavior +

+

+ Adds the calling convention specified by CcTag + to the pointer type T. +

+

+ + Notes +

+

+ For add_calling_convention + to work as-intended, you must: +

+
    +
  1. + Be programming on a platform that supports adding the desired calling convention + to type T +
  2. +
  3. + Define one or more of the following macros before including any CallableTraits + headers: +
      +
    • + CALLABLE_TRAITS_ENABLE_CDECL + for __cdecl +
    • +
    • + CALLABLE_TRAITS_ENABLE_STDCALL + for __stdcall +
    • +
    • + CALLABLE_TRAITS_ENABLE_FASTCALL + for __fastcall +
    • +
    • + CALLABLE_TRAITS_ENABLE_PASCAL + for pascal +
    • +
    +
  4. +
+
+ + + + + +
[Warning]Warning

+ This feature is currently considered experimental. Your feedback + is much appreciated! +

+

+ + Example + - __fastcall to __stdcall +

+
#define CALLABLE_TRAITS_ENABLE_STDCALL
+#define CALLABLE_TRAITS_ENABLE_FASTCALL
+
+#include <type_traits>
+#include <callable_traits/has_calling_convention.hpp>
+#include <callable_traits/add_calling_convention.hpp>
+#include <callable_traits/remove_calling_convention.hpp>
+
+namespace ct = callable_traits;
+
+int main() {
+
+    using f = void(__fastcall *)(int);
+
+    static_assert(ct::has_calling_convention<f, ct::fastcall_tag>(), "");
+    static_assert(!ct::has_calling_convention<f, ct::stdcall_tag>(), "");
+
+    using expect = void(__stdcall *)(int);
+
+    static_assert(ct::has_calling_convention<expect, ct::stdcall_tag>(), "");
+    static_assert(!ct::has_calling_convention<expect, ct::fastcall_tag>(), "");
+
+    using g = ct::remove_calling_convention<f>;
+    using test = ct::add_calling_convention<g, ct::stdcall_tag>;
+
+    static_assert(ct::has_calling_convention<test, ct::stdcall_tag>(), "");
+    static_assert(std::is_same<test, expect>::value, "");
+}
+
+

+ + Example + - __cdecl +

+
#define CALLABLE_TRAITS_ENABLE_CDECL
+
+#include <type_traits>
+#include <callable_traits/has_calling_convention.hpp>
+#include <callable_traits/add_calling_convention.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {};
+
+int main() {
+
+    //depending on your platform, pmf may already have an implicit __cdecl
+    using pmf = void(foo::*)();
+    using expect = void(__cdecl foo::*)();
+    using test = ct::add_calling_convention<pmf, ct::cdecl_tag>;
+
+    static_assert(std::is_same<test, expect>::value, "");
+    static_assert(ct::has_calling_convention<expect, ct::cdecl_tag>(), "");
+    static_assert(ct::has_calling_convention<test, ct::cdecl_tag>(), "");
+}
+
+

+ + See + Also +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_add_function_const.html b/doc/html/callable_traits/ref_add_function_const.html new file mode 100644 index 0000000..57e881b --- /dev/null +++ b/doc/html/callable_traits/ref_add_function_const.html @@ -0,0 +1,129 @@ + + + +add_function_const + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T>
+    using add_function_const = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be a Function or MemberFunctionPtr. +

+

+ + Behavior +

+

+ Adds a const qualifier to the + signature of T, if not already + present. In other words, int(foo::*)() + becomes int(foo::*)() const. +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/add_function_const.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {};
+
+int main() {
+
+    {
+        using pmf = int(foo::*)();
+        using expect = int(foo::*)() const;
+        using test = ct::add_function_const<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_const doesn't change anything when
+        // the function type is already const.
+        using pmf = int(foo::*)() const &&;
+        using expect = int(foo::*)() const &&;
+        using test = ct::add_function_const<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        using pmf = int(foo::*)() volatile &;
+        using expect = int(foo::*)() const volatile &;
+        using test = ct::add_function_const<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_const can also be used with "abominable"
+        // function types.
+        using f = int();
+        using expect = int() const;
+        using test = ct::add_function_const<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_const does not compile with function pointers,
+        // function references, function objects, or member data pointers.
+        // However, you can loosen this restriction somewhat by using the
+        // callable_traits::permissive namespace instead:
+        using f = int(*)();
+        using expect = f;
+        using test = ct::permissive::add_function_const<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+}
+
+

+ + See + Also +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_add_function_cv.html b/doc/html/callable_traits/ref_add_function_cv.html new file mode 100644 index 0000000..7421ff7 --- /dev/null +++ b/doc/html/callable_traits/ref_add_function_cv.html @@ -0,0 +1,134 @@ + + + +add_function_cv + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T>
+    using add_function_cv = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be a Function or MemberFunctionPtr. +

+

+ + Behavior +

+

+ Adds both const and volatile qualifiers to the signature of T, if not already present. In other words, + int(foo::*)() + becomes int(foo::*)() const volatile. +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/add_function_cv.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {};
+
+int main() {
+
+    {
+        using pmf = void(foo::*)();
+        using expect = void(foo::*)() const volatile;
+        using test = ct::add_function_cv<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_cv doesn't change anything when
+        // the function type is already cv-qualified.
+        using pmf = void(foo::*)() const volatile &&;
+        using expect = void(foo::*)() const volatile &&;
+        using test = ct::add_function_cv<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        using pmf = void(foo::*)() volatile &;
+        using expect = void(foo::*)() const volatile &;
+        using test = ct::add_function_cv<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_cv can also be used with "abominable"
+        // function types.
+        using f = void();
+        using expect = void() const volatile;
+        using test = ct::add_function_cv<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_cv does not compile with function pointers,
+        // function references, function objects, or member data pointers.
+        // However, you can loosen this restriction somewhat by using the
+        // callable_traits::permissive namespace instead:
+        using f = void(*)();
+        using expect = f;
+        using test = ct::permissive::add_function_cv<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+}
+
+

+ + See + Also +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_add_function_lvalue.html b/doc/html/callable_traits/ref_add_function_lvalue.html new file mode 100644 index 0000000..52d9715 --- /dev/null +++ b/doc/html/callable_traits/ref_add_function_lvalue.html @@ -0,0 +1,131 @@ + + + +add_function_lvalue + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T>
+    using add_function_lvalue = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be a Function or MemberFunctionPtr. +

+

+ + Behavior +

+

+ Adds an lvalue reference qualifier (&) + to the signature of T, if not + already present. In other words, void(foo::*)() + becomes void(foo::*)() &. +

+
#include <type_traits>
+#include <callable_traits/add_function_lvalue.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {};
+
+int main() {
+
+    {
+        using pmf = void(foo::*)();
+        using expect = void(foo::*)() &;
+        using test = ct::add_function_lvalue<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_lvalue doesn't change anything when
+        // the function type already has an lvalue qualifier.
+        using pmf = void(foo::*)() &;
+        using expect = void(foo::*)() &;
+        using test = ct::add_function_lvalue<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_lvalue models C++11 reference collapsing
+        // rules, so that adding an lvalue qualifier to an
+        // rvalue-qualified type will force the lvalue.
+        using pmf = void(foo::*)() &&;
+        using expect = void(foo::*)() &;
+        using test = ct::add_function_lvalue<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_lvalue can also be used to create "abominable"
+        // function types.
+        using f = void();
+        using expect = void() &;
+        using test = ct::add_function_lvalue<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_lvalue does not compile with function pointers,
+        // function references, function objects, or member data pointers.
+        // However, you can loosen this restriction somewhat by using the
+        // callable_traits::permissive namespace instead:
+        using f = void(*)();
+        using expect = f;
+        using test = ct::permissive::add_function_lvalue<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+}
+
+

+ + See + Also +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_add_function_rvalue.html b/doc/html/callable_traits/ref_add_function_rvalue.html new file mode 100644 index 0000000..c40b8e9 --- /dev/null +++ b/doc/html/callable_traits/ref_add_function_rvalue.html @@ -0,0 +1,132 @@ + + + +add_function_rvalue + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T>
+    using add_function_rvalue = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be a Function or MemberFunctionPtr. +

+

+ + Behavior +

+

+ Adds an rvalue reference qualifier (&&) + to the signature of T, if not + already present. In other words, void(foo::*)() + becomes void(foo::*)() &&. +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/add_function_rvalue.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {};
+
+int main() {
+
+    {
+        using pmf = void(foo::*)();
+        using expect = void(foo::*)() &&;
+        using test = ct::add_function_rvalue<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_rvalue doesn't change anything when
+        // the function type already has an rvalue qualifier.
+        using pmf = void(foo::*)() &&;
+        using expect = void(foo::*)() &&;
+        using test = ct::add_function_rvalue<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_rvalue models C++11 reference collapsing
+        // rules, so that adding an rvalue qualifier to an
+        // lvalue-qualified type will not change anything.
+        using pmf = void(foo::*)() const &;
+        using expect = void(foo::*)() const &;
+        using test = ct::add_function_rvalue<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_rvalue can also be used with "abominable"
+        // function types.
+        using f = void() const;
+        using expect = void() const &&;
+        using test = ct::add_function_rvalue<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_rvalue does not compile with function pointers,
+        // function references, function objects, or member data pointers.
+        // However, you can loosen this restriction somewhat by using the
+        // callable_traits::permissive namespace instead:
+        using f = void(*)();
+        using expect = f;
+        using test = ct::permissive::add_function_rvalue<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+}
+
+

+ + See + Also +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_add_function_volatile.html b/doc/html/callable_traits/ref_add_function_volatile.html new file mode 100644 index 0000000..c565ccb --- /dev/null +++ b/doc/html/callable_traits/ref_add_function_volatile.html @@ -0,0 +1,129 @@ + + + +add_function_volatile + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T>
+    using add_function_volatile = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be a Function or MemberFunctionPtr. +

+

+ + Behavior +

+

+ Adds a volatile qualifier to the + signature of T, if not already + present. In other words, void(foo::*)(char) becomes + void(foo::*)(char) volatile. +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/add_function_volatile.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {};
+
+int main() {
+
+    {
+        using pmf = void(foo::*)();
+        using expect = void(foo::*)() volatile;
+        using test = ct::add_function_volatile<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_volatile doesn't change anything when
+        // the function type is already volatile.
+        using pmf = void(foo::*)() volatile &&;
+        using expect = void(foo::*)() volatile &&;
+        using test = ct::add_function_volatile<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        using pmf = void(foo::*)() const &;
+        using expect = void(foo::*)() const volatile &;
+        using test = ct::add_function_volatile<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_volatile can also be used with "abominable"
+        // function types.
+        using f = void();
+        using expect = void() volatile;
+        using test = ct::add_function_volatile<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        // add_function_volatile does not compile with function pointers,
+        // function references, function objects, or member data pointers.
+        // However, you can loosen this restriction somewhat by using the
+        // callable_traits::permissive namespace instead:
+        using f = void(*)();
+        using expect = f;
+        using test = ct::permissive::add_function_volatile<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+}
+
+

+ + See + Also +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_add_varargs.html b/doc/html/callable_traits/ref_add_varargs.html new file mode 100644 index 0000000..908e7c2 --- /dev/null +++ b/doc/html/callable_traits/ref_add_varargs.html @@ -0,0 +1,143 @@ + + + +add_varargs + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T>
+    using add_varargs = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be one of the following: + * Function + * FunctionPtr + * FunctionReference + * MemberFunctionPtr +

+

+ + Behavior +

+

+ Adds C-style variadics (...) to + the signature of T, if not + already present. In other words, int(int) + becomes int(int, ...). +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/add_varargs.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {};
+
+int main() {
+
+    {
+        using f = void(int);
+        using expect = void(int, ...);
+        using test = ct::add_varargs<f>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        using fp = void(*)();
+        using expect = void(*)(...);
+        using test = ct::add_varargs<fp>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        using fr = void(&)(const char*);
+        using expect = void(&)(const char*, ...);
+        using test = ct::add_varargs<fr>;
+        static_assert(std::is_same<test, expect>::value, "");
+    } {
+        using pmf = void(foo::*)() const;
+        using expect = void(foo::*)(...) const;
+        using test = ct::add_varargs<pmf>;
+        static_assert(std::is_same<test, expect>::value, "");
+
+        // add_varargs doesn't change anything when
+        // the type already has varargs.
+        using twice = ct::add_varargs<test>;
+        static_assert(std::is_same<test, twice>::value, "");
+    }
+
+    // add_varargs fails in a SFINAE-friendly manner when
+    // used on a function object or a member data pointer.
+    //
+    // {
+    //     using d = int foo::*;
+    //     using test = ct::add_varargs<d>;
+    // }
+    //
+    // The error message is about as obvious as it can be without
+    // resorting to a SFINAE-unfriendly static_assert (namespaces
+    // omitted for brevity):
+    //
+    //   error: no type named 'type' in 'struct disjunction<
+    //   type_value<invalid_type, false>, add_varargs_error<0> >'
+}
+
+

+ + See + Also +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_apply_member_pointer.html b/doc/html/callable_traits/ref_apply_member_pointer.html new file mode 100644 index 0000000..0bb25dc --- /dev/null +++ b/doc/html/callable_traits/ref_apply_member_pointer.html @@ -0,0 +1,133 @@ + + + +apply_member_pointer + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T, typename Class>
+    using apply_member_pointer = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be one of the following: + * Function + * FunctionPtr + * FunctionReference + * MemberPtr +

+

+ + Behavior +

+

+ When T is a Function, FunctionPtr, or FunctionReference, the resulting type is a member + function pointer of class/struct Class, + with matching parameters and return type. When T + is a MemberPtr, + the resulting type is a member pointer of class/struct Class, + pointing to the same type as the original MemberPtr. +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/apply_member_pointer.hpp>
+
+namespace ct = callable_traits;
+
+struct foo;
+struct bar;
+
+using expect = int(foo::*)(int);
+
+int main() {
+
+    {
+        using f = int(int);
+        using test = ct::apply_member_pointer<f, foo>;
+        using expect = int(foo::*)(int);
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+
+    {
+        using f = int(* const &)(int);
+        using test = ct::apply_member_pointer<f, foo>;
+        using expect = int(foo::* const &)(int);
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+
+    {
+        using f = int(&)(int);
+        using test = ct::apply_member_pointer<f, foo>;
+        using expect = int(foo::*)(int);
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+
+    {
+        using f = int(foo::*)(int);
+        using test = ct::apply_member_pointer<f, foo>;
+        using expect = int(foo::*)(int);
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+
+    {
+        using f = int(bar::* const)(int);
+        using test = ct::apply_member_pointer<f, foo>;
+        using expect = int(foo::* const)(int);
+        static_assert(std::is_same<test, expect>::value, "");
+    }
+}
+
+

+ + See + Also +

+ +
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_apply_return.html b/doc/html/callable_traits/ref_apply_return.html new file mode 100644 index 0000000..9273ce7 --- /dev/null +++ b/doc/html/callable_traits/ref_apply_return.html @@ -0,0 +1,80 @@ + + + +apply_return + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +
namespace callable_traits {
+
+    template<typename T, typename Return>
+    using apply_return = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be one of the following: + * Function + * FunctionPtr + * FunctionReference + * MemberPtr +

+

+ + Behavior +

+

+ When T is a Function, FunctionPtr, FunctionReference, or MemberFunctionPtr, the resulting type's signature's + return type will be of type Return, + and the rest of the signature will be identical. When T + is a MemberDataPtr, + the resulting type points to a data member of type Return, + with the same parent class as T. +

+

+ + Example +

+

+ [apply_return] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_arg_at.html b/doc/html/callable_traits/ref_arg_at.html new file mode 100644 index 0000000..7a209aa --- /dev/null +++ b/doc/html/callable_traits/ref_arg_at.html @@ -0,0 +1,89 @@ + + + +arg_at + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+arg_at +

+
namespace callable_traits {
+
+    template<std::size_t Index, typename T>
+    using arg_at = /* implementation-defined */;
+
+}
+
+

+ + Constraints +

+

+ T must be a SimpleCallable. Index + must be less than ArgCount + and greater than zero, where ArgCount + is the number of arguments in the signature of T + (the signature of operator() + for SimpleFunctionObject). +

+

+ + Behavior +

+

+ When Index is outside the range + defined above, the substitution fails in a SFINAE-friendly manner. Otherwise, + the resulting type is the argument type at zero-based index Index. + In other words, arg_at<1, void(char, + short, long)> aliases + short. +

+

+ + Example +

+

+ [arg_at] +

+

+ + See + Also +

+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_args.html b/doc/html/callable_traits/ref_args.html new file mode 100644 index 0000000..b19b926 --- /dev/null +++ b/doc/html/callable_traits/ref_args.html @@ -0,0 +1,104 @@ + + + +args + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+args +

+

+ TODO +

+

+ + Example +

+
#include <type_traits>
+#include <memory>
+#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+// all callable types in this example use these parameter types
+using expect = std::tuple<int, float&, const char*>;
+
+template<typename T>
+void test(){
+    // this example shows how callable_traits::args
+    // bevaves consistently for many different types
+    using args = ct::args<T>;
+    static_assert(std::is_same<expect, args>{}, "");
+}
+
+int main() {
+
+
+    auto lamda = [](int, float&, const char*){};
+    using lam = decltype(lamda);
+    test<lam>();
+    test<lam&>();
+    test<lam&&>();
+    test<lam const &>();
+
+    struct foo;
+    using pmf = void(foo::*)(int, float&, const char*);
+    test<pmf>();
+    test<pmf&>();
+    test<pmf&&>();
+    test<pmf const &>();
+
+    using function_ptr = void(*)(int, float&, const char*);
+    test<function_ptr>();
+    test<function_ptr&>();
+    test<function_ptr&&>();
+    test<function_ptr const &>();
+
+    using function_ref = void(&)(int, float&, const char*);
+    test<function_ref>();
+
+    using function = void(int, float&, const char*);
+    test<function>();
+
+    using abominable = void(int, float&, const char*) const;
+    test<abominable>();
+}
+
+

+ + ??? +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_arity.html b/doc/html/callable_traits/ref_arity.html new file mode 100644 index 0000000..62907d4 --- /dev/null +++ b/doc/html/callable_traits/ref_arity.html @@ -0,0 +1,53 @@ + + + +arity + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+arity +

+

+ TODO +

+

+ + Example +

+

+ [arity] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_bind.html b/doc/html/callable_traits/ref_bind.html new file mode 100644 index 0000000..06da95b --- /dev/null +++ b/doc/html/callable_traits/ref_bind.html @@ -0,0 +1,176 @@ + + + +bind + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+

+bind +

+

+ TODO +

+

+ + Example + 1 +

+
/* In this example, the last _1 placeholder in the bind
+expression forces all other _1 slots to accept ScaryMonster,
+because ScaryMonster is the narrowest of all _1 parameters. */
+
+#include <cassert>
+#include <type_traits>
+#include <functional>
+#include <tuple>
+#include <callable_traits/callable_traits.hpp>
+
+struct Vampire {};
+struct Robot {};
+struct Animal {};
+struct Dog : Animal {};
+struct Poodle : Dog {};
+struct ScaryMonster : Vampire, Robot, Poodle {};
+
+auto vampire_to_robot(Vampire) {
+    return Robot{};
+}
+
+auto robot_to_dog = [](Robot){
+    return Dog{};
+};
+
+struct converter {
+    auto dog_to_vampire(Dog) {
+        return Vampire{};
+    }
+};
+
+int take_all(Vampire, Robot, Animal, Dog, Poodle, ScaryMonster) {
+    return 0;
+}
+
+using namespace std::placeholders;
+namespace ct = callable_traits;
+
+int main() {
+
+    auto b =
+        ct::bind(&take_all,
+            ct::bind(&converter::dog_to_vampire,
+                converter{},
+                ct::bind(robot_to_dog,
+                    ct::bind(&vampire_to_robot, _1)
+                )
+            ),
+            ct::bind(&vampire_to_robot, _3),
+            Animal{},
+            _1,
+            _2,
+            _1
+        );
+
+    {
+        using args = ct::args<decltype(b)>;
+        using expect = std::tuple<ScaryMonster, Poodle, Vampire>;
+        static_assert(std::is_same<args, expect>::value, "");
+    } {
+        using type = ct::function_type<decltype(b)>;
+        using expect = int(ScaryMonster, Poodle, Vampire);
+        static_assert(std::is_same<type, expect>::value, "");
+    }
+
+    assert(b(ScaryMonster{}, Poodle{}, Vampire{}) == 0);
+
+    return 0;
+}
+
+

+ + Example + 2 +

+
#include <cassert>
+#include <type_traits>
+#include <functional>
+#include <tuple>
+#include <callable_traits/callable_traits.hpp>
+
+struct Vampire {};
+struct Robot {};
+struct Animal {};
+struct Dog : Animal {};
+struct Poodle : Dog {};
+struct ScaryMonster : Poodle, Robot, Vampire {};
+
+auto take_vampire(const Vampire&) { return 0; }
+auto take_robot(const Robot&) { return 0; }
+auto take_dog(const Dog&) { return 0; }
+auto take_scary_monster(const ScaryMonster&) { return 0; }
+
+int f(int, int, int, int) { return 0; }
+
+using namespace std::placeholders;
+namespace ct = callable_traits;
+
+int main() {
+
+    ScaryMonster monster{};
+
+    auto b = ct::bind(
+        &f,
+        ct::bind(&take_vampire, _1),
+        ct::bind(&take_robot, _1),
+        ct::bind(&take_dog, _1),
+        ct::bind(&take_scary_monster, _1)
+    );
+
+    {
+        using args = ct::args<decltype(b)>;
+        using expect = std::tuple<const ScaryMonster&>;
+        static_assert(std::is_same<args, expect>::value, "");
+    } {
+        using type = ct::function_type<decltype(b)>;
+        using expect = int(const ScaryMonster&);
+        static_assert(std::is_same<type, expect>::value, "");
+    }
+
+    assert(b(monster) == 0);
+
+    return 0;
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_can_invoke.html b/doc/html/callable_traits/ref_can_invoke.html new file mode 100644 index 0000000..76c6a1c --- /dev/null +++ b/doc/html/callable_traits/ref_can_invoke.html @@ -0,0 +1,193 @@ + + + +can_invoke + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example - + Function Object +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+// For the purpose of this example, 'Bad' represents
+// any non-arithmetic type
+struct Bad {};
+Bad bad{};
+
+// non-generic callables, such as `subtract` below,
+// don't have any "gotchas" when passed to
+// callable_traits::can_invoke.
+auto subtract = [](int x, int y) {
+    return x + y;
+};
+
+static_assert(!ct::can_invoke(subtract), "");
+static_assert(!ct::can_invoke(subtract, 1), "");
+static_assert(ct::can_invoke(subtract, 1, 2), ""); // <-- success
+static_assert(!ct::can_invoke(subtract, 1, 2, 3), "");
+static_assert(!ct::can_invoke(subtract, bad, bad), "");
+
+// Generic function objects (such as `add` and `multiply` below)
+// must be SFINAE-friendly in order for failing can_invoke calls
+// to actually compile. This applies to both generic lambdas and
+// templated function objects. Note: MSVC does not compile this
+// source code file because of the trailing return type below (MSVC
+// is non-conforming in this respect)
+
+auto add = [](auto x, auto y) -> decltype(x + y) {
+    return x + y;          // ^^^^^^^^^^^^^^^^^^ explicit return type allows SFINAE
+};
+
+template<int I>
+using int_c = std::integral_constant<int, I>;
+
+static_assert(!ct::can_invoke(add), "");
+static_assert(!ct::can_invoke(add, 1), "");
+static_assert(ct::can_invoke(add, 1, 2), ""); // <-- success
+static_assert(!ct::can_invoke(add, 1, 2, 3), "");
+static_assert(!ct::can_invoke(add, bad, bad), "");
+
+// 'multiply' isn't SFINAE-safe, because the return type depends
+// on an expression in the body. However, it still works if we
+// only try to call can_invoke with arguments where x * y is
+// a valid expression.
+auto multiply = [](auto x, auto y) {
+    return x * y;
+};
+
+
+static_assert(!ct::can_invoke(multiply), "");
+static_assert(!ct::can_invoke(multiply, 1), "");
+static_assert(ct::can_invoke(multiply, 1, 2), ""); // <-- success
+static_assert(!ct::can_invoke(multiply, 1, 2, 3), "");
+//static_assert(!ct::can_invoke(multiply, bad, bad), "");
+
+// The last, commented static_assert above would fail compile,
+// because the call cannot be SFINAE'd away. Error message in Clang:
+// "invalid operands to binary expression ('Bad' and 'Bad')"
+
+int main() {}
+
+

+ + Example + - Member Function Pointer +

+
#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+struct foo {
+    int bar(int) const {
+        return 1;
+    }
+};
+
+// can_invoke returns std::true_type here because the
+// arguments are valid to INVOKE
+static_assert(ct::can_invoke(&foo::bar, foo{}, 0), "");
+
+// can_invoke returns std::false_type here because the
+// arguments are NOT valid to INVOKE - foo::bar can't be
+// invoked like a void member function.
+static_assert(!ct::can_invoke(&foo::bar, foo{}), "");
+
+int main() {}
+
+

+ + Example - + Function Pointer +

+
#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+int foo(int&& i) {
+    return i;
+}
+
+// can_invoke returns std::true_type here because the
+// arguments are valid to INVOKE
+static_assert(ct::can_invoke(&foo, 0), "");
+
+int i = 0;
+
+// can_invoke returns std::false_type here because the
+// arguments are NOT valid to INVOKE - foo expects an
+// rvalue reference, not an lvalue reference.
+static_assert(!ct::can_invoke(&foo, i), "");
+
+int main() {}
+
+

+ + Example + - Function Reference +

+
#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+int foo(int&& i) {
+    return i;
+}
+
+// can_invoke returns std::true_type here because the
+// arguments are valid to INVOKE
+static_assert(ct::can_invoke(foo, 0), "");
+
+int i = 0;
+
+// can_invoke returns std::false_type here because the
+// arguments are NOT valid to INVOKE - foo expects an
+// rvalue reference, not an lvalue reference.
+static_assert(!ct::can_invoke(foo, i), "");
+
+int main() {}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_can_invoke_constexpr.html b/doc/html/callable_traits/ref_can_invoke_constexpr.html new file mode 100644 index 0000000..3ac3344 --- /dev/null +++ b/doc/html/callable_traits/ref_can_invoke_constexpr.html @@ -0,0 +1,185 @@ + + + +can_invoke_constexpr + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example + - Function Object +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+// NOTE: Due to non-compliance in MSVC, can_invoke_constexpr
+// always return std::false_type on that compiler, which causes
+// the static asserts below to fail.
+
+namespace ct = callable_traits;
+
+using T1 = std::integral_constant<int, 3>;
+using T2 = std::integral_constant<int, 7>;
+
+//'subtract' is a constexpr function object that
+// subtracts std::integral_constant types.
+struct subtract {
+
+    // To compile failing cases of can_invoke_constexpr, the function object
+    // must have a SFINAE-safe signature. In this case, 'subtract' is made
+    // SFINAE-safe with an explicit, trailing return type.
+    template<typename T1, typename T2>
+    constexpr auto operator()(T1, T2) const -> decltype(T1::value - T2::value) {
+        return T1::value - T2::value;
+    }
+};
+
+// can_invoke_constexpr returns std::true_type in the first case, because
+// INVOKE(subtract{}, T1{}, T2{}) is a valid expression, AND 'subtract{}' is
+// a constexpr function object.
+static_assert(ct::can_invoke_constexpr(subtract{}, T1{}, T2{}), "");
+static_assert(!ct::can_invoke_constexpr(subtract{}, 3, 7), "");
+static_assert(!ct::can_invoke_constexpr(subtract{}, T1{}), "");
+
+//this is a function object, but is NOT constexpr
+struct add {
+    template<typename T1, typename T2>
+    auto operator()(T1, T2) const -> decltype(T1::value + T2::value) {
+        return T1::value + T2::value;
+    }
+};
+
+// Even though INVOKE(add{}, T1{}, T2{}) is valid, the respective
+// can_invoke_constexpr call returns std::false_type because 'add{}'
+// is not a constexpr function object.
+static_assert(!ct::can_invoke_constexpr(add{}, T1{}, T2{}), "");
+static_assert(!ct::can_invoke_constexpr(add{}, 3, 7), "");
+
+
+// This last section demonstrates that can_invoke_constexpr will always
+// return std::false_type when any of the arguments do not decay to literal
+// types. (see http://en.cppreference.com/w/cpp/concept/LiteralType).
+// Even though 'S' below is a constexpr function object, it is incompatible
+// with can_invoke_constexpr because 'S' isn't a literal type. Additionally,
+// all arguments must be default constructible.
+
+struct S {
+    S() = delete;
+    S(int){};
+    constexpr int operator()() const { return 0; }
+};
+
+S s{0};
+static_assert(!ct::can_invoke_constexpr(s), "");
+
+
+int main() {}
+
+

+ + Example + - Member Function Pointer +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+// NOTE: Due to non-compliance in MSVC, can_invoke_constexpr
+// always returns std::false_type on that compiler, which
+// causes a static assert below to fail.
+
+namespace ct = callable_traits;
+
+struct foo {
+    constexpr int bar(int) const {
+        return 1;
+    }
+};
+
+using pmf_constant = std::integral_constant<decltype(&foo::bar), &foo::bar>;
+
+// can_invoke_constexpr returns true here because foo::bar
+// is constexpr, and the arguments are valid to INVOKE
+static_assert(ct::can_invoke_constexpr(pmf_constant{}, foo{}, 0), "");
+
+// can_invoke_constexpr returns false here because even though
+// foo::bar is constexpr, the arguments do not obey INVOKE rules
+static_assert(!ct::can_invoke_constexpr(pmf_constant{}, foo{}), "");
+
+int main() {}
+
+

+ + Example + - Function Pointer +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+constexpr int seven(int) {
+    return 7;
+}
+
+using seven_c = std::integral_constant<decltype(&seven), &seven>;
+
+// The first call to can_invoke_constexpr returns std::true_type
+// because `seven` is a constexpr function, and valid INVOKE arguments
+// are passed. The second call to can_invoke_constexpr returns
+// std::false_type, because the arguments are not valid to INVOKE
+static_assert(ct::can_invoke_constexpr(seven_c{}, 0), "");
+static_assert(!ct::can_invoke_constexpr(seven_c{}, nullptr), "");
+
+int eight(int) {
+    return 7;
+}
+
+using eight_c = std::integral_constant<decltype(&eight), &eight>;
+
+// `eight` is NOT a constexpr function, so can_invoke_constexpr
+// returns `std::false_type` even for valid INVOKE arguments.
+static_assert(!ct::can_invoke_constexpr(eight_c{}, 0), "");
+static_assert(!ct::can_invoke_constexpr(eight_c{}, nullptr), "");
+
+int main() {}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_function_type.html b/doc/html/callable_traits/ref_function_type.html new file mode 100644 index 0000000..f5b641c --- /dev/null +++ b/doc/html/callable_traits/ref_function_type.html @@ -0,0 +1,90 @@ + + + +function_type + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+template<typename T>
+void test(){
+
+    // this example shows how callable_traits::function_type
+    // bevaves consistently for many different types
+    using type = ct::function_type<T>;
+    using expect = void(int, float&, const char*);
+    static_assert(std::is_same<expect, type>{}, "");
+}
+
+int main() {
+
+    auto lamda = [](int, float&, const char*){};
+    using lam = decltype(lamda);
+    test<lam>();
+    test<lam&>();
+    test<lam&&>();
+    test<lam const &>();
+
+    using function_ptr = void(*)(int, float&, const char*);
+    test<function_ptr>();
+    test<function_ptr&>();
+    test<function_ptr&&>();
+    test<function_ptr const &>();
+
+    using function_ref = void(&)(int, float&, const char*);
+    test<function_ref>();
+
+    using function = void(int, float&, const char*);
+    test<function>();
+
+    using abominable = void(int, float&, const char*) const;
+    test<abominable>();
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_has_calling_convention.html b/doc/html/callable_traits/ref_has_calling_convention.html new file mode 100644 index 0000000..8bb7cb9 --- /dev/null +++ b/doc/html/callable_traits/ref_has_calling_convention.html @@ -0,0 +1,80 @@ + + + +has_calling_convention + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example + - __fastcall to __stdcall +

+
#define CALLABLE_TRAITS_ENABLE_STDCALL
+#define CALLABLE_TRAITS_ENABLE_FASTCALL
+
+#include <type_traits>
+#include <callable_traits/has_calling_convention.hpp>
+#include <callable_traits/add_calling_convention.hpp>
+#include <callable_traits/remove_calling_convention.hpp>
+
+namespace ct = callable_traits;
+
+int main() {
+
+    using f = void(__fastcall *)(int);
+
+    static_assert(ct::has_calling_convention<f, ct::fastcall_tag>(), "");
+    static_assert(!ct::has_calling_convention<f, ct::stdcall_tag>(), "");
+
+    using expect = void(__stdcall *)(int);
+
+    static_assert(ct::has_calling_convention<expect, ct::stdcall_tag>(), "");
+    static_assert(!ct::has_calling_convention<expect, ct::fastcall_tag>(), "");
+
+    using g = ct::remove_calling_convention<f>;
+    using test = ct::add_calling_convention<g, ct::stdcall_tag>;
+
+    static_assert(ct::has_calling_convention<test, ct::stdcall_tag>(), "");
+    static_assert(std::is_same<test, expect>::value, "");
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_has_varargs.html b/doc/html/callable_traits/ref_has_varargs.html new file mode 100644 index 0000000..ccf2867 --- /dev/null +++ b/doc/html/callable_traits/ref_has_varargs.html @@ -0,0 +1,53 @@ + + + +has_varargs + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [has_varargs] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_has_void_return.html b/doc/html/callable_traits/ref_has_void_return.html new file mode 100644 index 0000000..464833d --- /dev/null +++ b/doc/html/callable_traits/ref_has_void_return.html @@ -0,0 +1,53 @@ + + + +has_void_return + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [has_void_return] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_is_const_qualified.html b/doc/html/callable_traits/ref_is_const_qualified.html new file mode 100644 index 0000000..c8bf044 --- /dev/null +++ b/doc/html/callable_traits/ref_is_const_qualified.html @@ -0,0 +1,53 @@ + + + +is_const_qualified + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [is_const_qualified] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_is_constexpr.html b/doc/html/callable_traits/ref_is_constexpr.html new file mode 100644 index 0000000..a9d9e59 --- /dev/null +++ b/doc/html/callable_traits/ref_is_constexpr.html @@ -0,0 +1,173 @@ + + + +is_constexpr + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example + - Function Object +

+
+ + + + + +
[Warning]Warning

+ When compiling in MSVC, is_constexpr + always returns std::false_type, because MSVC cannot compile + the logic that normally determines this. +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+//this is a constexpr function object (non-templated)
+struct zero {
+
+    constexpr auto operator()() const {
+        return 0;
+    }
+};
+
+static_assert(ct::is_constexpr<zero>(), "");
+static_assert(ct::is_constexpr(zero{}), "");
+
+
+
+//this is a constexpr function object (templated)
+struct subtract {
+
+    // For callable_traits::is_constexpr, generic function objects
+    // only need to be SFINAE-friendly if the body of the operator()
+    // function accesses member names besides "type" and "value".
+    // Unary/binary operators and constructor calls are okay to use.
+    template<typename T1, typename T2>
+    constexpr auto operator()(T1, T2) const {
+        return T1{} - T2{};
+    }
+};
+
+static_assert(ct::is_constexpr<subtract>(), "");
+static_assert(ct::is_constexpr(subtract{}), "");
+
+
+
+//this is NOT a constexpr function object
+struct add {
+    template<typename T1, typename T2>
+    auto operator()(T1, T2) const {
+        return T1{} + T2{};
+    }
+};
+
+static_assert(!ct::is_constexpr<add>(), "");
+static_assert(!ct::is_constexpr(add{}), "");
+
+auto multiply = [](auto t1, auto t2) -> decltype(t1.value * t2.value) {
+    return t1.value * t2.value;
+};
+
+static_assert(!ct::is_constexpr<decltype(multiply)>(), "");
+static_assert(!ct::is_constexpr(multiply), "");
+
+
+// is_constexpr will always return std::false_type when the argument
+// is either not a literal type, or is not default constructible. Below,
+// divide is not default constructible, so is_constexpr returns
+// std::false_type. For literal types that are default constructible, a
+// constexpr default constructor is assumed.
+
+struct divide {
+
+    divide() = delete;
+    constexpr divide(int){};
+
+    template<typename T1, typename T2>
+    constexpr auto operator()(T1, T2) const {
+        return T1{} / T2{};
+    }
+};
+
+static_assert(!ct::is_constexpr<divide>(), "");
+static_assert(!ct::is_constexpr(divide{0}), "");
+
+int main() {}
+
+

+ + Example + - Function Pointer +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+// NOTE: Due to non-compliance in MSVC, is_constexpr always
+// returns std::false_type on that compiler, which causes
+// the static asserts below to fail.
+
+namespace ct = callable_traits;
+
+constexpr int foo(const int&) {
+    return 1;
+}
+
+int bar(const int&) {
+    return 1;
+}
+
+// for is_constexpr calls, function pointers must
+// be passed as std::integral_constants
+using F = std::integral_constant<decltype(&foo), &foo>;
+using B = std::integral_constant<decltype(&bar), &bar>;
+
+static_assert(ct::is_constexpr(F{}), "");
+static_assert(ct::is_constexpr<F>(), "");
+static_assert(!ct::is_constexpr(B{}), "");
+static_assert(!ct::is_constexpr<B>(), "");
+
+int main() {}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_is_lvalue_qualified.html b/doc/html/callable_traits/ref_is_lvalue_qualified.html new file mode 100644 index 0000000..fb20492 --- /dev/null +++ b/doc/html/callable_traits/ref_is_lvalue_qualified.html @@ -0,0 +1,53 @@ + + + +is_lvalue_qualified + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [is_lvalue_qualified] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_is_qualified.html b/doc/html/callable_traits/ref_is_qualified.html new file mode 100644 index 0000000..811700d --- /dev/null +++ b/doc/html/callable_traits/ref_is_qualified.html @@ -0,0 +1,53 @@ + + + +is_qualified + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [is_qualified] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_is_reference_qualified.html b/doc/html/callable_traits/ref_is_reference_qualified.html new file mode 100644 index 0000000..1d2339f --- /dev/null +++ b/doc/html/callable_traits/ref_is_reference_qualified.html @@ -0,0 +1,53 @@ + + + +is_reference_qualified + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [is_reference_qualified] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_is_rvalue_qualified.html b/doc/html/callable_traits/ref_is_rvalue_qualified.html new file mode 100644 index 0000000..c81edfb --- /dev/null +++ b/doc/html/callable_traits/ref_is_rvalue_qualified.html @@ -0,0 +1,53 @@ + + + +is_rvalue_qualified + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [is_rvalue_qualified] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_is_volatile_qualified.html b/doc/html/callable_traits/ref_is_volatile_qualified.html new file mode 100644 index 0000000..92a4104 --- /dev/null +++ b/doc/html/callable_traits/ref_is_volatile_qualified.html @@ -0,0 +1,53 @@ + + + +is_volatile_qualified + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [is_volatile_qualified] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_max_arity.html b/doc/html/callable_traits/ref_max_arity.html new file mode 100644 index 0000000..9c96907 --- /dev/null +++ b/doc/html/callable_traits/ref_max_arity.html @@ -0,0 +1,53 @@ + + + +max_arity + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [max_arity] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_min_arity.html b/doc/html/callable_traits/ref_min_arity.html new file mode 100644 index 0000000..11d99f7 --- /dev/null +++ b/doc/html/callable_traits/ref_min_arity.html @@ -0,0 +1,53 @@ + + + +min_arity + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [min_arity] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_qualified_function_type.html b/doc/html/callable_traits/ref_qualified_function_type.html new file mode 100644 index 0000000..63237db --- /dev/null +++ b/doc/html/callable_traits/ref_qualified_function_type.html @@ -0,0 +1,53 @@ + + + +qualified_function_type + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [qualified_function_type] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_remove_calling_convention.html b/doc/html/callable_traits/ref_remove_calling_convention.html new file mode 100644 index 0000000..e7465ca --- /dev/null +++ b/doc/html/callable_traits/ref_remove_calling_convention.html @@ -0,0 +1,80 @@ + + + +remove_calling_convention + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example + - __fastcall to __stdcall +

+
#define CALLABLE_TRAITS_ENABLE_STDCALL
+#define CALLABLE_TRAITS_ENABLE_FASTCALL
+
+#include <type_traits>
+#include <callable_traits/has_calling_convention.hpp>
+#include <callable_traits/add_calling_convention.hpp>
+#include <callable_traits/remove_calling_convention.hpp>
+
+namespace ct = callable_traits;
+
+int main() {
+
+    using f = void(__fastcall *)(int);
+
+    static_assert(ct::has_calling_convention<f, ct::fastcall_tag>(), "");
+    static_assert(!ct::has_calling_convention<f, ct::stdcall_tag>(), "");
+
+    using expect = void(__stdcall *)(int);
+
+    static_assert(ct::has_calling_convention<expect, ct::stdcall_tag>(), "");
+    static_assert(!ct::has_calling_convention<expect, ct::fastcall_tag>(), "");
+
+    using g = ct::remove_calling_convention<f>;
+    using test = ct::add_calling_convention<g, ct::stdcall_tag>;
+
+    static_assert(ct::has_calling_convention<test, ct::stdcall_tag>(), "");
+    static_assert(std::is_same<test, expect>::value, "");
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_remove_function_const.html b/doc/html/callable_traits/ref_remove_function_const.html new file mode 100644 index 0000000..2488bbc --- /dev/null +++ b/doc/html/callable_traits/ref_remove_function_const.html @@ -0,0 +1,53 @@ + + + +remove_function_const + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [remove_function_const] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_remove_function_cv.html b/doc/html/callable_traits/ref_remove_function_cv.html new file mode 100644 index 0000000..f592d71 --- /dev/null +++ b/doc/html/callable_traits/ref_remove_function_cv.html @@ -0,0 +1,53 @@ + + + +remove_function_cv + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [remove_function_cv] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_remove_function_reference.html b/doc/html/callable_traits/ref_remove_function_reference.html new file mode 100644 index 0000000..0fe9e8e --- /dev/null +++ b/doc/html/callable_traits/ref_remove_function_reference.html @@ -0,0 +1,53 @@ + + + +remove_function_reference + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [remove_function_reference] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_remove_function_volatile.html b/doc/html/callable_traits/ref_remove_function_volatile.html new file mode 100644 index 0000000..588ff33 --- /dev/null +++ b/doc/html/callable_traits/ref_remove_function_volatile.html @@ -0,0 +1,53 @@ + + + +remove_function_volatile + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [remove_function_volatile] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_remove_member_pointer.html b/doc/html/callable_traits/ref_remove_member_pointer.html new file mode 100644 index 0000000..19b5d96 --- /dev/null +++ b/doc/html/callable_traits/ref_remove_member_pointer.html @@ -0,0 +1,85 @@ + + + +remove_member_pointer + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+struct foo;
+
+template<typename T, typename Expect>
+void test() {
+    using U = ct::remove_member_pointer<T>;
+    static_assert(std::is_same<Expect, U>{}, "");
+}
+
+int main() {
+
+    {
+        using T = int(foo::*)(int) const;
+        using expect = int(int) const;
+        test<T, expect>();
+    } {
+        using T = int foo::*;
+        using expect = int;
+        test<T, expect>();
+    } {
+        using T = int(int);
+        test<T, T>();
+    } {
+        using T = int(*)(int);
+        test<T, T>();
+    } {
+        using T = int(&)(int);
+        test<T, T>();
+    }
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_remove_varargs.html b/doc/html/callable_traits/ref_remove_varargs.html new file mode 100644 index 0000000..814092d --- /dev/null +++ b/doc/html/callable_traits/ref_remove_varargs.html @@ -0,0 +1,53 @@ + + + +remove_varargs + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+

+ [remove_varargs] +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/callable_traits/ref_result_of.html b/doc/html/callable_traits/ref_result_of.html new file mode 100644 index 0000000..cca066c --- /dev/null +++ b/doc/html/callable_traits/ref_result_of.html @@ -0,0 +1,78 @@ + + + +result_of + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ TODO +

+

+ + Example +

+
#include <type_traits>
+#include <callable_traits/callable_traits.hpp>
+
+namespace ct = callable_traits;
+
+using expect = int;
+
+struct foo;
+
+template<typename T>
+void test() {
+    using result = ct::result_of<T>;
+    static_assert(std::is_same<expect, result>{}, "");
+}
+
+int main() {
+
+    test<int()>();
+    test<int(*)()>();
+    test<int(&)()>();
+    test<int() const>();
+    test<int(foo::*)() const>();
+
+    auto x = []() -> int { return 0; };
+
+    test<decltype(x)>();
+}
+
+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/index.html b/doc/html/index.html index 0b2dc33..3bbcff1 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@
More

-
Next
+
Next
@@ -41,55 +41,74 @@
Introduction
+
Prerequisite Topics
Motivation
Quick Example
-
Concept - Definitions
-
Why use CallableTraits?
-
Use case:std::function - sugar
+
What makes CallableTraits + unique?
-
Reference
+
Example:std::function + sugar
+
Compatibility
+
MSVC Issues
+
Concepts
-
Headers
-
add_calling_convention
-
add_function_const
-
add_function_cv
-
add_function_lvalue
-
add_function_rvalue
-
add_varargs
-
add_function_volatile
-
apply_member_pointer
-
apply_return
-
arg_at
-
args
-
arity
-
bind
-
can_invoke
-
can_invoke_constexpr
-
function_type
-
has_calling_convention
-
has_varargs
-
has_void_return
-
is_const_qualified
-
is_constexpr
-
is_lvalue_qualified
-
is_reference_qualified
-
is_rvalue_qualified
-
is_qualified
-
is_volatile_qualified
-
max_arity
-
min_arity
-
qualified_function_type
-
remove_calling_convention
-
remove_function_const
-
remove_function_cv
-
remove_member_pointer
-
remove_function_reference
-
remove_varargs
-
remove_function_volatile
-
result_of
+
FunctionPtr
+
FunctionReference
+
UnqualifiedFunction
+
AbominableFunction
+
Function
+
MemberFunctionPtr
+
MemberDataPtr
+
MemberPtr
+
SimpleFunctionObject
+
OverloadedFunctionObject
+
FunctionObject
+
Callable
+
SimpleCallable
+
SimpleInvokable
+
Invokable
+
ConstexprDefaultConstructible
+
CallingConventionTag
+
Headers
+
add_calling_convention
+
add_function_const
+
add_function_cv
+
add_function_lvalue
+
add_function_rvalue
+
add_varargs
+
add_function_volatile
+
apply_member_pointer
+
apply_return
+
arg_at
+
args
+
arity
+
bind
+
can_invoke
+
can_invoke_constexpr
+
function_type
+
has_calling_convention
+
has_varargs
+
has_void_return
+
is_const_qualified
+
is_constexpr
+
is_lvalue_qualified
+
is_reference_qualified
+
is_rvalue_qualified
+
is_qualified
+
is_volatile_qualified
+
max_arity
+
min_arity
+
qualified_function_type
+
remove_calling_convention
+
remove_function_const
+
remove_function_cv
+
remove_member_pointer
+
remove_function_reference
+
remove_varargs
+
remove_function_volatile
+
result_of
Acknowledgements
Contact
@@ -99,97 +118,97 @@ Introduction

-
+

+ CallableTraits is a cross-platform C++14 library for the + inspection, decomposition, and synthesis of C++ callable types. CallableTraits + is header-only, and does not depend on any non-standard headers. CallableTraits + is currently hosted at GitHub. +

+
- - + +
[Important]Important[Note]Note

CallableTraits is not a Boost library.

+
+

- CallableTraits is a cross-platform C++14 library for the - inspection, decomposition, and synthesis of C++ callable types. CallableTraits - is header-only, and does not depend on any non-standard headers. -

-

- This documentation will be most beneficial to readers with a basic understanding - of the syntax and usage of the following C++ features: -

+ This documentation will be most beneficial to readers who posess a basic + understanding of the following C++ features: +

-

- The CallableTraits development repository is hosted at - GitHub. -

+

Motivation @@ -370,7 +389,7 @@ using expected_args = std::tuple<int, int&&, const int&, void*>; static_assert(std::is_same<args, expected_args>::value, ""); - // callable_traits::function_type "decays" a callable type to a plain + // [libns]function_type "decays" a callable type to a plain // function type, which is structured in terms of INVOKE. using function_type = ct::function_type<foo>; using expected_function_type = void(int, int&&, const int&, void*); @@ -408,7 +427,7 @@ int i = 0; - // callable_traits::can_invoke allows us to preview whether + // [libns]can_invoke allows us to preview whether // std::invoke would compile with the given arguments. static_assert(ct::can_invoke(foo{}, 0, 0, i), ""); // no error: std::invoke(foo{}, 0, 0, i); @@ -461,7 +480,7 @@ using with_rvalue = void (foo::*)(int, int&&, const int&, void*) const &&; static_assert(std::is_same<rvalue_pmf, with_rvalue>::value, ""); - // Just like std::add_rvalue_reference, callable_traits::add_function_rvalue + // Just like std::add_rvalue_reference, [libns]add_function_rvalue // follows C++11 reference collapsing rules. While remove_function_const // and add_function_rvalue are somewhat clumsy names, they are the best // the best the author could provide while still allowing both terseness @@ -486,237 +505,12 @@

-

- CallableTraits relies on the following concepts, and will - be referenced throughout this documentation: -

-
- - FunctionPtr -
-
    -
  • - Any function pointer type -
  • -
  • - the pointer may be cv-qualified and/or ref-qualified -
  • -
  • - e.g. void(*)(int, int) or - void(* - const &)(int, int) -
  • -
-
- - FunctionReference -
-
    -
  • - Any function reference type -
  • -
  • - e.g. void(&)(int, int) -
  • -
-
- - Function -
-
    -
  • - Any unqualified function type -
  • -
  • - e.g. void(int, int) -
  • -
-
- - AbominableFunction -
-
    -
  • - Any qualified (a.k.a. "abominable") - function type -
  • -
  • - Not technically "callable", but still falls under the CallableTraits - umbrella -
  • -
  • - Mutually exclusive with Function -
  • -
  • - e.g. void(int, int) const -
  • -
-
- - MemberFunctionPtr -
-
    -
  • - Any pointer to member function type -
  • -
  • - The pointer type may be cv-qualified and/or ref-qualified -
  • -
  • - e.g. void (foo::*)(int, int) -
  • -
-
- - MemberDataPtr -
-
    -
  • - Any pointer to data member type -
  • -
  • - The pointer type may be cv-qualified and/or ref-qualified -
  • -
  • - e.g. int foo::* -
  • -
-
- - SimpleFunctionObject -
-
    -
  • - Any class/struct with a non-templated, non-overloaded - function call operator -
  • -
  • - Includes non-generic lambda types -
  • -
  • - May be cv-qualified and/or ref-qualified. -
  • -
  • - Mutually exclusive with OverloadedFunctionObject -
  • -
  • - e.g. the type of this lambda: [](int x, int y) { return x + y; } -
  • -
-
- - OverloadedFunctionObject -
-
    -
  • - Any class/struct with a templated or overloaded - function call operator, with the following limitation for those with - templated function call operators (which includes generic lambdas): -
    -
  • -
  • - May be cv-qualified and/or ref-qualified -
  • -
  • - e.g. the type of this generic lambda: [](auto x, auto y) { return x + y; } -
  • -
-
- - - - - -
[Tip]Tip

- Generic lambdas or classes with templated function objects that are either - not SFINAE-friendly or rely on dependent names for template instantiations - are generally incompatible with CallableTraits. -

-
- - FunctionObject -
-
-
- - Callable -
-
-
- - SimpleCallable -
-
-
- - SimpleInvokable -
-
-
- - Invokable -
-
-
- - ConstexprDefaultConstructible -
-
  • - Any LiteralType - that is also default-constructible -
-
-
-

1. CallableTraits offers - template aliases such as remove_function_const + template aliases such as remove_function_const for manipulating function qualifiers, designed to parallel the <type_traits> aliases such as std::remove_const_t.

@@ -728,42 +522,43 @@

3. CallableTraits is - designed in terms of the INVOKE - rules, with one unobtrusive and beneficial deviation: Function - types and AbominableFunction types are compatible - with all operations that do not specifically require an invocation. + designed to comply with INVOKE + rules, with one unobtrusive and beneficial deviation: Function types types are compatible with all + relevant type operations that do not specifically require an invocation.

- 4. callable_traits::arg_at<2, Callable> is both more flexible and more readable - than typename boost::function_traits<Callable>::arg3_type. + 4. callable_traits::arg_at<2, + Callable> + is more flexible (arguable more readable) than typename + boost::function_traits<Callable>::arg3_type.

- 5. callable_traits::can_invoke can be used to test INVOKE-ability at compile-time, with value - semantics. For the craziest metaprogrammers, callable_traits::can_invoke_constexpr does the same as - can_invoke for ConstexprDefaultConstructible - types, with an added check for constexpr-ness + 5. can_invoke + is used to test INVOKE-ability + at compile-time, with value semantics. For the craziest metaprogrammers, + can_invoke_constexpr + does the same as can_invoke + for ConstexprDefaultConstructible types, with an + added check for constexpr-ness (Note: for can_invoke_constexpr, - argument types must also be ConstexprDefaultConstructible) + argument types must also be ConstexprDefaultConstructible)

- 6. callable_traits::is_constexpr can be used to check whether - a ConstexprDefaultConstructible type is a - Callable type that yields a constexpr + 6. is_constexpr + is used to check whether a ConstexprDefaultConstructible type is a Callable + type that yields a constexpr result -- no arguments necessary.

- 7. callable_traits::bind can be used by library writers to - easily accept std::placeholder expressions anywhere, and "intercept" - the type information before forwarding to std::bind - or boost::bind. This allows for more flexible APIs, - where a function template taking a "callable type" can be overloaded - to also accept placeholder expressions. It's perhaps a small improvement - from requiring std::bind first, but in API design, even the - smallest things count. See + 7. bind + is used by library writers to easily accept std::placeholder + expressions anywhere, and intercept the type information for processing before + forwarding on to std::bind or boost::bind. + This gives library writers the power to create more flexible templated APIs.

- 8. callable_traits::min_arity can be used to detect the presence - of default arguments on a SimpleFunctionObject + 8. min_arity + is used to detect the presence of default arguments on a SimpleFunctionObject

9. The CallableTraits @@ -785,126 +580,6 @@ and are not yet fully tested on any platform.

-
- -

- At the time of this writing, there are around 260 search - results on Stack Overflow concerning the conversion from std::bind - to std::function. There are roughly 340 search - results concerning the conversion of lambdas to std::function. - In the example below, we'll kill both birds with the same stone. The make_function function will leverage CallableTraits - to... -

-
    -
  1. - Create an std::function<T> - where T is not explicitly supplied by the user -
  2. -
  3. - Create an std::function<T> - where T is the deduced "signature" of an std::placeholders - expression. -
  4. -
-

- Without real-world context, make_function - may seem rather silly to those who know the runtime costs of type erasure. - However, whenever std::function is required by some 3rd party - API, this example might make a bit more sense. -

-
#include <functional>
-#include <callable_traits/function_type.hpp>
-#include <callable_traits/bind.hpp>
-
-namespace example_library {
-
-    namespace ct = callable_traits;
-
-    // make_function turns a non-overloaded callable into a type-erased std::function object
-    template<typename T>
-    inline decltype(auto) make_function(T&& t) {
-
-        // callable_traits::function_type decays any non-overloaded callable type to
-        // a plain function type, which is structured in terms of INVOKE.
-
-        using signature = ct::function_type<T&&>;
-        using result_type = std::function<signature>;
-        return result_type{ std::forward<T>(t) };
-    }
-
-    // this make_function overload turns a bind expression into a type-erased std::function object
-    template<typename T, typename First, typename... Others>
-    inline decltype(auto) make_function(T&& t, First&& first, Others&&... others) {
-
-        // callable_traits::bind is essentially a compile-time parser of placeholder
-        // expressions, for the purpose of retaining more type information than
-        // std::bind normally allows - specifically, callable_traits::bind is used to
-        // determine the de-facto signature of the std::bind return type, with special
-        // considerations for conversions between reused placeholders and nested
-        // placeholder expressions. For the sake of convenience, callable_traits::bind
-        // is also a thin forwarding wrapper around std::bind (which is the only true
-        // runtime element in CallableTraits).
-
-        using bind_expr = decltype(ct::bind(
-                std::forward<T>(t),
-                std::forward<First>(first),
-                std::forward<Others>(others)...
-        ));
-
-        using signature = ct::function_type<bind_expr>;
-        using result_type = std::function<signature>;
-
-        return result_type{ std::bind(
-                std::forward<T>(t),
-                std::forward<First>(first),
-                std::forward<Others>(others)...
-        )};
-    }
-}
-
-// client code starts here
-#include <cassert>
-
-using namespace example_library;
-using namespace std::placeholders;
-
-int add(int i, int j) {
-    return i + j;
-}
-
-struct adder {
-
-    int eval(int i, int j) const {
-        return i + j;
-    }
-};
-
-int main() {
-
-    // function pointer
-    auto f = make_function(&add);
-    assert(f(99, 1) == 100);
-
-    // function reference
-    f = make_function(add);
-    assert(f(99, 1) == 100);
-
-    // member function pointer (bound to object)
-    f = make_function(&adder::eval, adder{}, _1, _2);
-    assert(f(99, 1) == 100);
-
-    // lambda
-    f = make_function([](int i, int j) {
-        return i + j;
-    });
-
-    assert(f(99, 1) == 100);
-}
-
-
@@ -912,6 +587,6 @@

-
Next
+
Next
diff --git a/doc/html/standalone_HTML.manifest b/doc/html/standalone_HTML.manifest index 166b454..b8114a6 100644 --- a/doc/html/standalone_HTML.manifest +++ b/doc/html/standalone_HTML.manifest @@ -1,4 +1,44 @@ index.html -callable_traits/ref.html +callable_traits/function_sugar_example.html +callable_traits/compatibility.html +callable_traits/concepts.html +callable_traits/headers.html +callable_traits/ref_add_calling_convention.html +callable_traits/ref_add_function_const.html +callable_traits/ref_add_function_cv.html +callable_traits/ref_add_function_lvalue.html +callable_traits/ref_add_function_rvalue.html +callable_traits/ref_add_varargs.html +callable_traits/ref_add_function_volatile.html +callable_traits/ref_apply_member_pointer.html +callable_traits/ref_apply_return.html +callable_traits/ref_arg_at.html +callable_traits/ref_args.html +callable_traits/ref_arity.html +callable_traits/ref_bind.html +callable_traits/ref_can_invoke.html +callable_traits/ref_can_invoke_constexpr.html +callable_traits/ref_function_type.html +callable_traits/ref_has_calling_convention.html +callable_traits/ref_has_varargs.html +callable_traits/ref_has_void_return.html +callable_traits/ref_is_const_qualified.html +callable_traits/ref_is_constexpr.html +callable_traits/ref_is_lvalue_qualified.html +callable_traits/ref_is_reference_qualified.html +callable_traits/ref_is_rvalue_qualified.html +callable_traits/ref_is_qualified.html +callable_traits/ref_is_volatile_qualified.html +callable_traits/ref_max_arity.html +callable_traits/ref_min_arity.html +callable_traits/ref_qualified_function_type.html +callable_traits/ref_remove_calling_convention.html +callable_traits/ref_remove_function_const.html +callable_traits/ref_remove_function_cv.html +callable_traits/ref_remove_member_pointer.html +callable_traits/ref_remove_function_reference.html +callable_traits/ref_remove_varargs.html +callable_traits/ref_remove_function_volatile.html +callable_traits/ref_result_of.html callable_traits/acknowledgements.html callable_traits/contact.html diff --git a/example/add_function_const.cpp b/example/add_function_const.cpp index 5ff2239..b2a0df1 100644 --- a/example/add_function_const.cpp +++ b/example/add_function_const.cpp @@ -15,27 +15,27 @@ struct foo {}; int main() { { - using pmf = void(foo::*)(); - using expect = void(foo::*)() const; + using pmf = int(foo::*)(); + using expect = int(foo::*)() const; using test = ct::add_function_const; static_assert(std::is_same::value, ""); } { // add_function_const doesn't change anything when // the function type is already const. - using pmf = void(foo::*)() const &&; - using expect = void(foo::*)() const &&; + using pmf = int(foo::*)() const &&; + using expect = int(foo::*)() const &&; using test = ct::add_function_const; static_assert(std::is_same::value, ""); } { - using pmf = void(foo::*)() volatile &; - using expect = void(foo::*)() const volatile &; + using pmf = int(foo::*)() volatile &; + using expect = int(foo::*)() const volatile &; using test = ct::add_function_const; static_assert(std::is_same::value, ""); } { // add_function_const can also be used with "abominable" // function types. - using f = void(); - using expect = void() const; + using f = int(); + using expect = int() const; using test = ct::add_function_const; static_assert(std::is_same::value, ""); } { @@ -43,7 +43,7 @@ int main() { // function references, function objects, or member data pointers. // However, you can loosen this restriction somewhat by using the // callable_traits::permissive namespace instead: - using f = void(*)(); + using f = int(*)(); using expect = f; using test = ct::permissive::add_function_const; static_assert(std::is_same::value, ""); diff --git a/example/add_function_volatile.cpp b/example/add_function_volatile.cpp new file mode 100644 index 0000000..a1c2a87 --- /dev/null +++ b/example/add_function_volatile.cpp @@ -0,0 +1,52 @@ +/*<- +Copyright Barrett Adair 2016 +Distributed under the Boost Software License, Version 1.0. +(See accompanying file LICENSE.md or copy at http ://boost.org/LICENSE_1_0.txt) +->*/ + +//[ add_function_volatile +#include +#include + +namespace ct = callable_traits; + +struct foo {}; + +int main() { + + { + using pmf = void(foo::*)(); + using expect = void(foo::*)() volatile; + using test = ct::add_function_volatile; + static_assert(std::is_same::value, ""); + } { + // add_function_volatile doesn't change anything when + // the function type is already volatile. + using pmf = void(foo::*)() volatile &&; + using expect = void(foo::*)() volatile &&; + using test = ct::add_function_volatile; + static_assert(std::is_same::value, ""); + } { + using pmf = void(foo::*)() const &; + using expect = void(foo::*)() const volatile &; + using test = ct::add_function_volatile; + static_assert(std::is_same::value, ""); + } { + // add_function_volatile can also be used with "abominable" + // function types. + using f = void(); + using expect = void() volatile; + using test = ct::add_function_volatile; + static_assert(std::is_same::value, ""); + } { + // add_function_volatile does not compile with function pointers, + // function references, function objects, or member data pointers. + // However, you can loosen this restriction somewhat by using the + // callable_traits::permissive namespace instead: + using f = void(*)(); + using expect = f; + using test = ct::permissive::add_function_volatile; + static_assert(std::is_same::value, ""); + } +} +//] diff --git a/qtcreator/main/main.cpp b/qtcreator/main/main.cpp index 73080ac..a1c2a87 100644 --- a/qtcreator/main/main.cpp +++ b/qtcreator/main/main.cpp @@ -1,57 +1,52 @@ /*<- -Copyright (c) 2016 Barrett Adair - +Copyright Barrett Adair 2016 Distributed under the Boost Software License, Version 1.0. -(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) +(See accompanying file LICENSE.md or copy at http ://boost.org/LICENSE_1_0.txt) ->*/ -//[ apply_member_pointer +//[ add_function_volatile #include -#include +#include namespace ct = callable_traits; -struct foo; -struct bar; - -using expect = int(foo::*)(int); +struct foo {}; int main() { { - using f = int(int); - using test = ct::apply_member_pointer; - using expect = int(foo::*)(int); + using pmf = void(foo::*)(); + using expect = void(foo::*)() volatile; + using test = ct::add_function_volatile; static_assert(std::is_same::value, ""); - } - - { - using f = int(* const &)(int); - using test = ct::apply_member_pointer; - using expect = int(foo::* const &)(int); + } { + // add_function_volatile doesn't change anything when + // the function type is already volatile. + using pmf = void(foo::*)() volatile &&; + using expect = void(foo::*)() volatile &&; + using test = ct::add_function_volatile; static_assert(std::is_same::value, ""); - } - - { - using f = int(&)(int); - using test = ct::apply_member_pointer; - using expect = int(foo::*)(int); + } { + using pmf = void(foo::*)() const &; + using expect = void(foo::*)() const volatile &; + using test = ct::add_function_volatile; static_assert(std::is_same::value, ""); - } - - { - using f = int(foo::*)(int); - using test = ct::apply_member_pointer; - using expect = int(foo::*)(int); + } { + // add_function_volatile can also be used with "abominable" + // function types. + using f = void(); + using expect = void() volatile; + using test = ct::add_function_volatile; static_assert(std::is_same::value, ""); - } - - { - using f = int(bar::* const)(int); - using test = ct::apply_member_pointer; - using expect = int(foo::* const)(int); + } { + // add_function_volatile does not compile with function pointers, + // function references, function objects, or member data pointers. + // However, you can loosen this restriction somewhat by using the + // callable_traits::permissive namespace instead: + using f = void(*)(); + using expect = f; + using test = ct::permissive::add_function_volatile; static_assert(std::is_same::value, ""); } } //] -