// Copyright ⓒ 2018-2021 ThePhD.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//  See https://github.com/ThePhD/out_ptr/blob/master/docs/out_ptr.adoc for documentation.

[[config]]
# Configuring ztd.out_ptr

There are macro definitions one can employ for their project's build to change the behavior and safety of ztd.out_ptr.

* `ZTD_OUT_PTR_NO_CLEVERNESS`
** When defined, will change from using an aliasing optimization for `std::unique_ptr` and `boost::movelib` to simply using the default, stock behavior of retrieving the pointer value and then calling `.reset()` to put it back.
** This is noticeably slower (see the <<benchmarks.adoc#benchmarks, benchmarks>> for more information), but obviously safer since we are not aliasing into private members.
** This is *not* defined by default under any circumstances.
* `ZTD_OUT_PTR_CLEVER_UNIQUE_IMPLEMENTATION_FIRST_MEMBER` / `ZTD_OUT_PTR_CLEVER_MOVELIB_UNIQUE_IMPLEMENTATION_FIRST_MEMBER`
** If defined and not 0, this tells any clever optimizations for `unique`-style pointers (e.g. `std::unique_ptr` and `boost::movelib::unique_ptr`) that the pointer member comes first, rather than after any stored deleter.
** To date, no standard library has been found to have this class layout. But future ones may.
** This is *not* defined by default under any circumstances.
* `ZTD_OUT_PTR_USE_CLEVER_OUT_PTR`
** This applies specifically to `ztd::out_ptr::out_ptr` and not to `ztd::out_ptr::inout_ptr`.
** If defined and not 0, switches the implementation for `out_ptr` to be an unsafe clever version.
** This is *dangerous*: many C APIs do not modify the parameter on return, making it impossible to directly reseat the value inside the pointer properly!
** This is *dangerous*: aliasing memory to access private members is UB!
** This is *not* defined by default under any circumstances.
* `ZTD_OUT_PTR_USE_CLEVER_INOUT_PTR`
** This applies specifically to `ztd::out_ptr::inout_ptr` and not to `ztd::out_ptr::out_ptr`.
** If defined and not 0, switches the implementation for `inout_ptr` to be an unsafe clever version.
** This is *dangerous*: aliasing memory to access private members is UB!
** This **is turned on** by default for when the following standard library version macros are present and it has not already been defined:
*** - `_LIBCPP_VERSION`: works with libc++, which uses the "pointer first, deleter second" layout. As such, `ZTD_OUT_PTR_CLEVER_UNIQUE_IMPLEMENTATION_FIRST_MEMBER` and are defined if they have not already been defined.
*** - `__GLIBC__`: works with libstdc++, which uses the "deleter first, pointer second" layout.
*** - `_YVALS` or `_CPPLIB_VER`: works with Visual C++'s standard library, which uses the "deleter first, pointer second" layout.
*** - boost::movelib uses first, second layouting as well

* `ZTD_OUT_PTR_CLEVER_SANITY_CHECK`
** If either of the `ZTD_OUT_PTR_USE_CLEVER*` defined and not equal to zero, and this is both defined and not 0, then ztd.out_ptr will do a check on the value aliased out of the pointer to make sure it has a value equivalent to `my_smart_ptr.get()`.
** For debugging and sanity checking purposes.
** This is *not* defined by default under any circumstances.
