From 6a72bc3560dbc17c812784317a03e71417f321ea Mon Sep 17 00:00:00 2001 From: afeher Date: Wed, 6 Nov 2024 14:37:03 -0500 Subject: [PATCH 01/11] Implement unwrap_reference, unwrap_ref_decay. --- groups/bsl/bsl+bslhdrs/bsl_functional.h | 2 +- groups/bsl/bslmf/bslmf_referencewrapper.cpp | 21 + groups/bsl/bslmf/bslmf_referencewrapper.h | 288 ++++++++++ groups/bsl/bslmf/bslmf_referencewrapper.t.cpp | 501 ++++++++++++++++++ groups/bsl/bslmf/bslmf_removereference.h | 2 +- groups/bsl/bslmf/bslmf_removereference.t.cpp | 2 +- groups/bsl/bslmf/bslmf_unwraprefdecay.cpp | 23 + groups/bsl/bslmf/bslmf_unwraprefdecay.h | 191 +++++++ groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 439 +++++++++++++++ groups/bsl/bslmf/bslmf_unwrapreference.cpp | 23 + groups/bsl/bslmf/bslmf_unwrapreference.h | 131 +++++ groups/bsl/bslmf/bslmf_unwrapreference.t.cpp | 314 +++++++++++ groups/bsl/bslmf/package/bslmf.mem | 3 + groups/bsl/bslstl/bslstl_referencewrapper.h | 260 +-------- .../bsl/bslstl/bslstl_referencewrapper.t.cpp | 425 ++------------- 15 files changed, 1985 insertions(+), 640 deletions(-) create mode 100644 groups/bsl/bslmf/bslmf_referencewrapper.cpp create mode 100644 groups/bsl/bslmf/bslmf_referencewrapper.h create mode 100644 groups/bsl/bslmf/bslmf_referencewrapper.t.cpp create mode 100644 groups/bsl/bslmf/bslmf_unwraprefdecay.cpp create mode 100644 groups/bsl/bslmf/bslmf_unwraprefdecay.h create mode 100644 groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp create mode 100644 groups/bsl/bslmf/bslmf_unwrapreference.cpp create mode 100644 groups/bsl/bslmf/bslmf_unwrapreference.h create mode 100644 groups/bsl/bslmf/bslmf_unwrapreference.t.cpp diff --git a/groups/bsl/bsl+bslhdrs/bsl_functional.h b/groups/bsl/bsl+bslhdrs/bsl_functional.h index f9e194a2bf..4312fddb34 100644 --- a/groups/bsl/bsl+bslhdrs/bsl_functional.h +++ b/groups/bsl/bsl+bslhdrs/bsl_functional.h @@ -129,7 +129,7 @@ namespace bsl { #include #include #include -#include +#include #endif // INCLUDED_BSL_FUNCTIONAL diff --git a/groups/bsl/bslmf/bslmf_referencewrapper.cpp b/groups/bsl/bslmf/bslmf_referencewrapper.cpp new file mode 100644 index 0000000000..ea2916d1de --- /dev/null +++ b/groups/bsl/bslmf/bslmf_referencewrapper.cpp @@ -0,0 +1,21 @@ +// bslmf_referencewrapper.cpp -*-C++-*- +#include + +#include +BSLS_IDENT("$Id$ $CSID$") + +// ---------------------------------------------------------------------------- +// Copyright 2013 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_referencewrapper.h b/groups/bsl/bslmf/bslmf_referencewrapper.h new file mode 100644 index 0000000000..54e90c7ff8 --- /dev/null +++ b/groups/bsl/bslmf/bslmf_referencewrapper.h @@ -0,0 +1,288 @@ +// bslmf_referencewrapper.h -*-C++-*- +#ifndef INCLUDED_BSLMF_REFERENCEWRAPPER +#define INCLUDED_BSLMF_REFERENCEWRAPPER + +#include +BSLS_IDENT("$Id: $") + +//@PURPOSE: Provide copyable, assignable object wrapper for references. +// +//@CLASSES: +// bsl::reference_wrapper: class object to hold a reference to an object +// +//@CANONICAL_HEADER: bsl_functional.h +// +//@DESCRIPTION: This component provides `bsl::reference_wrapper`, a reduced +// implementation of the standard C++2011 template of the same name, which +// simply wraps a reference into a copyable, assignable object to allow it to +// be stored in a place that cannot normally hold a reference, such as a +// standard container. Because a reference wrapper is convertible to its +// contained reference type, it can be passed to functions that take such a +// reference. +// +// This component also provides the (free) helper functions `bsl::ref` and +// `bsl::cref` that may be used to generate `reference_wrapper` objects more +// concisely than with the constructor. +// +// NOTE: This component is a partial implementation of the standard class, +// omitting support for use as a function object, and is in any case of +// limited usefulness in a pure C++98 environment. +// +///Usage +///----- +// This section illustrates intended use of this component. +// +///Example 1: Sorted References +/// - - - - - - - - - - - - - - +// Let us suppose that we wish to handle objects that will be passed to a +// comparison function expecting references to the objects. Let us suppose +// further that these objects are large enough that we would not wish to move +// them around bodily as they are sorted. Note that plausible examples of uses +// for this component are limited in freestanding C++98. +// +// First, let us define the large-object type: +// ``` +// struct Canary { +// static const int s_size = 1000; +// Canary *d_values[s_size]; +// Canary(); +// }; +// +// Canary::Canary() +// { +// for (int i = 0; i < s_size; ++i) { +// d_values[i] = this; +// } +// } +// ``` +// Next, we define the comparison function: +// ``` +// bool operator<(Canary const& a, Canary const& b) +// { +// return a.d_values[0] < b.d_values[0]; +// } +// ``` +// Finally, we define a generic function to sort two items: +// ``` +// template +// void sortTwoItems(T& a, T& b) +// { +// if (b < a) { +// T tmp(a); +// a = b; +// b = tmp; +// } +// } +// ``` +// We can call `sortTwoItems` on wrappers representing `Canary` objects +// without need to move actual, large `Canary` objects about. In the call to +// `sortTwoItems`, below, the `operator=` used in it is that of +// `bsl::reference_wrapper`, but the `operator<` used is the one +// declared for `Canary&` arguments. All of the conversions needed are +// applied implicitly: +// ``` +// Canary canaries[2]; +// bsl::reference_wrapper canaryA = bsl::ref(canaries[1]); +// bsl::reference_wrapper canaryB = bsl::ref(canaries[0]); +// sortTwoItems(canaryA, canaryB); +// +// assert(&canaryA.get() == canaries); +// assert(&canaryB.get() == canaries + 1); +// ``` + +#include + +#include +#include + +#include +#include +#include // for BloombergLP::bsls::Util::addressOf + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY +#include + +#define BSLMF_REFERENCEWRAPPER_IS_ALIASED + +namespace bsl { +using std::cref; +using std::ref; +using std::reference_wrapper; +} // close enterprise namespace +#endif + +#ifndef BSLMF_REFERENCEWRAPPER_IS_ALIASED +namespace bsl { + + // ======================= + // class reference_wrapper + // ======================= + +/// This class is a wrapper that encapsulates an object reference, enabling +/// operations not possible on actual references, including assignment, +/// copying, and storage in standard containers. When stored in a +/// container, it enables functions defined to operate on references to the +/// type represented to be called on the container elements. +template +class reference_wrapper { + + private: + // DATA + T *d_represented_p; // the represented object (not owned) + + public: + // TYPES + typedef T type; + + // CREATORS + + /// Create a reference wrapper representing the specified `object`. + reference_wrapper(T& object) BSLS_KEYWORD_NOEXCEPT; // IMPLICIT + + //! reference_wrapper(const reference_wrapper& original) = default; + // Create a reference wrapper referring to the same object as the + // specified 'original'. + + //! ~reference_wrapper() = default; + // Destroy this object. + + // MANIPULATORS + //! reference_wrapper& operator=(const reference_wrapper& rhs) = default; + // Assign this object to refer to the same object as the specified + // 'rhs', and return '*this'. + + // ACCESSORS + + /// Return a reference to the object that `*this` represents. + T& get() const BSLS_KEYWORD_NOEXCEPT; + + /// Return a reference to the object that `*this` represents. + operator T&() const BSLS_KEYWORD_NOEXCEPT; +}; + +// FREE FUNCTIONS + +/// Return a reference wrapper representing a `const` view of the specified +/// `object`. +template +reference_wrapper cref(const T& object) BSLS_KEYWORD_NOEXCEPT; + +template +reference_wrapper cref(reference_wrapper original) + BSLS_KEYWORD_NOEXCEPT; + // Return a reference wrapper representing a 'const' view of the same + // object as the specified 'original'. + +/// Return a reference wrapper that represents the specified `object`. +template +reference_wrapper ref(T& object) BSLS_KEYWORD_NOEXCEPT; + +/// Return a reference wrapper that represents the same object as the +/// specified `original`. +template +reference_wrapper ref(reference_wrapper original) BSLS_KEYWORD_NOEXCEPT; + +} // close namespace bsl + +// ============================================================================ +// INLINE DEFINITIONS +// ============================================================================ + + // ----------------------- + // class reference_wrapper + // ----------------------- + +// CREATORS +template +inline +bsl::reference_wrapper::reference_wrapper(T& object) BSLS_KEYWORD_NOEXCEPT + : d_represented_p(BloombergLP::bsls::Util::addressOf(object)) +{ +} + +// ACCESSORS +template +inline +T& bsl::reference_wrapper::get() const BSLS_KEYWORD_NOEXCEPT +{ + return *d_represented_p; +} + +template +inline +bsl::reference_wrapper::operator T&() const BSLS_KEYWORD_NOEXCEPT +{ + return *d_represented_p; +} + +// FREE FUNCTIONS +template +inline +bsl::reference_wrapper bsl::cref(const T& object) + BSLS_KEYWORD_NOEXCEPT +{ + return reference_wrapper(object); +} + +template +inline +bsl::reference_wrapper bsl::cref(bsl::reference_wrapper original) + BSLS_KEYWORD_NOEXCEPT +{ + return cref(original.get()); +} + +template +inline +bsl::reference_wrapper bsl::ref(T& object) BSLS_KEYWORD_NOEXCEPT +{ + return reference_wrapper(object); +} + +template +inline +bsl::reference_wrapper bsl::ref(bsl::reference_wrapper original) + BSLS_KEYWORD_NOEXCEPT +{ + return ref(original.get()); +} + +// TRAITS + +namespace BloombergLP { +namespace bslmf { + +template +struct IsBitwiseMoveable > : bsl::true_type { }; + +} // close namespace bslmf +} // close enterprise namespace + +#endif // BSLMF_REFERENCEWRAPPER_IS_ALIASED + +namespace BloombergLP { +namespace bslmf { + +template +struct IsReferenceWrapper > : bsl::true_type { }; + +} // close namespace bslmf +} // close enterprise namespace + +#endif + +// ---------------------------------------------------------------------------- +// Copyright 2013 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_referencewrapper.t.cpp b/groups/bsl/bslmf/bslmf_referencewrapper.t.cpp new file mode 100644 index 0000000000..9780c99fde --- /dev/null +++ b/groups/bsl/bslmf/bslmf_referencewrapper.t.cpp @@ -0,0 +1,501 @@ +// bslmf_referencewrapper.t.cpp -*-C++-*- +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +// ============================================================================ +// TEST PLAN +// ---------------------------------------------------------------------------- +// Overview +// -------- +// The component under test is fully specified by the standard, verifiable by +// inspection. Therefore, testing only exercises basic uses to ensure template +// specializations may be instantiated successfully. +// +// ---------------------------------------------------------------------------- +// TESTING INSTANTIATIONS AND BASIC FUNCTIONALITY +// [ 1] reference_wrapper(T&); +// [ 1] reference_wrapper(const reference_wrapper&); +// [ 1] reference_wrapper& operator=(reference_wrapper&); +// [ 1] operator T&() const; +// [ 1] T& get() const; +// [ 3] operator()(...) const; +// [ 1] reference_wrapper cref(const T&); +// [ 1] reference_wrapper cref(reference_wrapper); +// [ 1] reference_wrapper ref(T&); +// [ 1] reference_wrapper ref(reference_wrapper); +// ---------------------------------------------------------------------------- +// [ 4] USAGE EXAMPLE +// [ 2] TYPE TRAITS + +// ============================================================================ +// STANDARD BSL ASSERT TEST FUNCTION +// ---------------------------------------------------------------------------- + +namespace { + +int testStatus = 0; + +void aSsErT(bool condition, const char *message, int line) +{ + if (condition) { + printf("Error " __FILE__ "(%d): %s (failed)\n", line, message); + + if (0 <= testStatus && testStatus <= 100) { + ++testStatus; + } + } +} + +} // close unnamed namespace + +// ============================================================================ +// STANDARD BSL TEST DRIVER MACRO ABBREVIATIONS +// ---------------------------------------------------------------------------- + +#define ASSERT BSLS_BSLTESTUTIL_ASSERT +#define ASSERTV BSLS_BSLTESTUTIL_ASSERTV + +#define LOOP_ASSERT BSLS_BSLTESTUTIL_LOOP_ASSERT +#define LOOP0_ASSERT BSLS_BSLTESTUTIL_LOOP0_ASSERT +#define LOOP1_ASSERT BSLS_BSLTESTUTIL_LOOP1_ASSERT +#define LOOP2_ASSERT BSLS_BSLTESTUTIL_LOOP2_ASSERT +#define LOOP3_ASSERT BSLS_BSLTESTUTIL_LOOP3_ASSERT +#define LOOP4_ASSERT BSLS_BSLTESTUTIL_LOOP4_ASSERT +#define LOOP5_ASSERT BSLS_BSLTESTUTIL_LOOP5_ASSERT +#define LOOP6_ASSERT BSLS_BSLTESTUTIL_LOOP6_ASSERT + +#define Q BSLS_BSLTESTUTIL_Q // Quote identifier literally. +#define P BSLS_BSLTESTUTIL_P // Print identifier and value. +#define P_ BSLS_BSLTESTUTIL_P_ // P(X) without '\n'. +#define T_ BSLS_BSLTESTUTIL_T_ // Print a tab (w/o newline). +#define L_ BSLS_BSLTESTUTIL_L_ // current Line number + +// ============================================================================ +// GLOBAL TYPEDEFS/CONSTANTS FOR TESTING +// ---------------------------------------------------------------------------- + +struct Callable { + void operator()() { } + int operator()(int) { return 42; } + int operator()(int) const { return -42; } +}; + +/// Test class that is not bitwise movable +struct NonBitwiseDummy { + int d_data; + + explicit NonBitwiseDummy(int v = 0) : d_data(v) { } + NonBitwiseDummy(const NonBitwiseDummy& rhs) : d_data(rhs.d_data) {} +}; + +// ============================================================================ +// TEST FACILITIES +// ---------------------------------------------------------------------------- + +struct Dummy { + void operator&(); + const Dummy *localAddressOf() const { return this; } +}; +/// These functions are used solely to verify that a `reference_wrapper` can +/// be passed to a function expecting an actual reference. +bool isConst(Dummy&) { return false; } +bool isConst(const Dummy&) { return true; } + +// ============================================================================ +// USAGE EXAMPLE CLASSES AND FUNCTIONS +// ---------------------------------------------------------------------------- + +// Disable specific bde_verify warnings where practice of usage example may +// differ. + +// BDE_VERIFY pragma: push +// BDE_VERIFY pragma: -FD01 // Function needs contract, we probably should fix +// BDE_VERIFY pragma: -IND01 // Code is aligned as-if following a `//` comment + + +namespace TEST_CASE_USAGE { + +///Usage +///----- +// This section illustrates intended use of this component. +// +///Example 1: Sorted References +/// - - - - - - - - - - - - - - +// Let us suppose that we wish to handle objects that will be passed to a +// comparison function expecting references to the objects. Let us suppose +// further that these objects are large enough that we would not wish to move +// them around bodily as they are sorted. Note that plausible examples of uses +// for this component are limited in freestanding C++98. +// +// First, let us define the large-object type: +// ``` + struct Canary { + static const int s_size = 1000; + Canary *d_values[s_size]; + Canary(); + }; +// ``` + Canary::Canary() + { + for (int i = 0; i < s_size; ++i) { + d_values[i] = this; + } + } +// ``` +// Next, we define the comparison function: +// ``` + bool operator<(Canary const& a, Canary const& b) + { + return a.d_values[0] < b.d_values[0]; + } +// ``` +// Finally, we define a generic function to sort two items: +// ``` + template + void sortTwoItems(T& a, T& b) + { + if (b < a) { + T tmp(a); + a = b; + b = tmp; + } + } +// ``` +} // close namespace TEST_CASE_USAGE + +// BDE_VERIFY pragma: pop + +// ============================================================================ +// MAIN PROGRAM +// ---------------------------------------------------------------------------- + +int main(int argc, char *argv[]) +{ + int test = argc > 1 ? atoi(argv[1]) : 0; + bool verbose = argc > 2; + bool veryVerbose = argc > 3; + bool veryVeryVerbose = argc > 4; + bool veryVeryVeryVerbose = argc > 5; + + (void) veryVerbose; // unused variable warning + (void) veryVeryVerbose; // unused variable warning + (void)veryVeryVeryVerbose; // unused variable warning + + printf("TEST " __FILE__ " CASE %d\n", test); + + switch (test) { case 0: + case 4: { + // -------------------------------------------------------------------- + // USAGE EXAMPLE + // Extracted from component header file. + // + // Concerns: + // 1. The usage example in the component header file compiles, links, + // and runs as shown. + // + // Plan: + // 1. Incorporate usage example from header into test driver, remove + // leading comment characters, and replace `assert` with `ASSERT`. + // (C-1) + // + // Testing: + // USAGE EXAMPLE + // -------------------------------------------------------------------- + + if (verbose) puts("\nUSAGE EXAMPLE" + "\n============="); + + using namespace TEST_CASE_USAGE; + +// Disable specific bde_verify warnings where practice of usage example may +// differ. + +// BDE_VERIFY pragma: push +// BDE_VERIFY pragma: -FD01 // Function needs contract, we probably should fix +// BDE_VERIFY pragma: -IND01 // Code is aligned as-if following a `//` comment + +// ``` +// We can call `sortTwoItems` on wrappers representing `Canary` objects +// without need to move actual, large `Canary` objects about. In the call to +// `sortTwoItems`, below, the `operator=` used in it is that of +// `bsl::reference_wrapper`, but the `operator<` used is the one +// declared for `Canary&` arguments. All of the conversions needed are +// applied implicitly: +// ``` + Canary canaries[2]; + + bsl::reference_wrapper canaryA = bsl::ref(canaries[1]); + bsl::reference_wrapper canaryB = bsl::ref(canaries[0]); + sortTwoItems(canaryA, canaryB); +// + ASSERT(&canaryA.get() == canaries); + ASSERT(&canaryB.get() == canaries + 1); +// ``` + +// BDE_VERIFY pragma: pop + + } break; + case 3: { + // -------------------------------------------------------------------- + // TESTING CALLABLE + // Testing that bsl::reference_wrapper is callable (in C++11) + // + // Concerns: + // 1. That in appropriate build modes, bsl::reference_wrapper is + // callable + // + // Plan: + // 1. Verify `BSLMF_REFERENCEWRAPPER_IS_ALIASED` is `true` on + // on C++14 platforms. Note that this test is a sanity check + // and deliberately does not reproduce the logic in the component. + // + // 2. Verify if `BSLMF_REFERENCEWRAPPER_IS_ALIASED` is `true` + // `bsl::reference_wrapper` is an alias to the platform standard + // library. + // + // 3. Verify if `BSLMF_REFERENCEWRAPPER_IS_ALIASED` we can + // assign a function reference to a `reference_wrapper` and + // invoke it. + // + // Testing: + // operator()(...) const; + // -------------------------------------------------------------------- + + if (verbose) puts("\nTESTING CALLABLE" + "\n================"); + +#if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201402L +#ifndef BSLMF_REFERENCEWRAPPER_IS_ALIASED + BSLMF_ASSERT(false && "reference_wrapper not aliased in C++14"); +#endif // BSLMF_REFERENCEWRAPPER_IS_ALIASED +#endif // At least C++14 + +#ifdef BSLMF_REFERENCEWRAPPER_IS_ALIASED + if (verbose) puts("\tverify `reference_wrapper` is an alias to std"); + + ASSERT(true == + (bsl::is_same, + bsl::reference_wrapper >::value)); + + if (verbose) puts("\tverify `reference_wrapper` is callable"); + + { + Callable c; + bsl::reference_wrapper ref = bsl::ref(c); + ref(); + ASSERT(42 == ref(0)); + } + { + Callable c; + bsl::reference_wrapper ref = bsl::cref(c); + ASSERT(-42 == ref(0)); + } +#endif // BSLMF_REFERENCEWRAPPER_IS_ALIASED + + } break; + case 2: { + // -------------------------------------------------------------------- + // TYPE TRAITS + // + // Concerns: + // 1. `bslmf::IsBitwiseMoveable>::value` is + // true regardless of the type of `T`. + // + // 2. `bslmf::IsReferenceWrapper>::value` is + // true regardless of the type of `T`. + // + // Plan: + // 1. For concern 1, instantiate `reference_wrapper` with both bitwise + // moveable and non-bitwise moveable types and verify that the + // `bslmf::isBitwiseMovable` trait is true for both cases. + // + // 2. For concern 2, instantiate `reference_wrapper` with 2 + // unrelated types and verify that the `bslmf::IsReferenceWrapper` + // trait is true for both cases. + // + // Testing: + // TYPE TRAITS + // -------------------------------------------------------------------- + + if (verbose) puts("\nTYPE TRAITS" + "\n==========="); + + using BloombergLP::bslmf::IsBitwiseMoveable; + using BloombergLP::bslmf::IsReferenceWrapper; + using bsl::reference_wrapper; + + // First, verify that we have one bitwise movable type and one not + // bitwise movable type. + ASSERT( IsBitwiseMoveable::value); + ASSERT(! IsBitwiseMoveable::value); + + // Now test that `reference_wrapper` is bitwise movable in either + // case. + ASSERT(IsBitwiseMoveable >::value); + ASSERT(IsBitwiseMoveable >::value); + + // Test that `reference_wrapper` is indeed a reference wrapper. + ASSERT( IsReferenceWrapper >::value); + ASSERT( IsReferenceWrapper >::value); + + // Test that the trait specialization provided by this component does + // not incidentally cause `IsReferenceWrapper` to be true for actual + // reference types. + ASSERT(! IsReferenceWrapper::value); + ASSERT(! IsReferenceWrapper::value); + + } break; + case 1: { + // -------------------------------------------------------------------- + // BASIC TESTS + // Create objects each possible way, verify they have the right + // contents and can be used in the standard ways. + // + // Concerns: + // 1. Template functions defined are only checked by the compiler when + // called, so all templates must be instantiated here. + // + // 2. The various functions' argument must be copied into the object + // correctly. + // + // 3. The accessors must reproduce the various functions' argument + // values. + // + // Plan: + // 1. Define a dummy type. + // + // 2. Wrap the dummy type using each available method. + // + // 3. Use the wrappers' explicit and implicit accessors. (C-1..3) + // + // Testing: + // reference_wrapper(T&); + // reference_wrapper(const reference_wrapper&); + // reference_wrapper& operator=(reference_wrapper&); + // operator T&() const; + // T& get() const; + // reference_wrapper cref(const T&); + // reference_wrapper cref(reference_wrapper); + // reference_wrapper ref(T&); + // reference_wrapper ref(reference_wrapper); + // -------------------------------------------------------------------- + + if (verbose) puts("\nBASIC TESTS" + "\n==========="); + + Dummy a; + const Dummy b = {}; + + ASSERT(!isConst(a) && isConst(b)); // Test `isConst`. + + bsl::reference_wrapper< Dummy> rwa (a); + bsl::reference_wrapper rwca(a); + bsl::reference_wrapper rwcb(b); + + bsl::reference_wrapper< Dummy> copyrwa (rwa ); + bsl::reference_wrapper copyrwca(rwca); + bsl::reference_wrapper copyrwcb(rwcb); + + ASSERT(!isConst(rwa)); // Check conversion to ref type, constness. + ASSERT( isConst(rwca)); // Likewise. + ASSERT( isConst(rwcb)); + + copyrwa = a; // Assign from raw reference. + copyrwca = a; // Likewise. + copyrwcb = b; + + copyrwa = rwa; // Assign from other `reference_wrapper`. + copyrwca = rwca; // Likewise. + copyrwcb = rwcb; + + Dummy& rax = rwa; // Initialize from `reference_wrapper`. + const Dummy& rcax = rwca; // Likewise. + const Dummy& rcbx = rwcb; + + Dummy& ray = bsl::ref(a); // Initialize from ref result. + const Dummy& rcay = bsl::cref(a); // Likewise. + const Dummy& rcby = bsl::cref(b); + + ASSERT(!isConst(bsl::ref (a))); + ASSERT( isConst(bsl::cref(a))); + ASSERT( isConst(bsl::cref(b))); + + ASSERT(!isConst(bsl::ref (rwa ))); + ASSERT( isConst(bsl::cref(rwca))); + ASSERT( isConst(bsl::cref(rwcb))); + + bsl::reference_wrapper< Dummy> copyrwaz (bsl::ref(rwa )); + bsl::reference_wrapper copyrwcaz(bsl::ref(rwca)); + bsl::reference_wrapper copyrwcbz(bsl::ref(rwcb)); + + bsl::reference_wrapper copyrwcazb(bsl::cref(rwca)); + bsl::reference_wrapper copyrwcbzc(bsl::cref(rwcb)); + + Dummy c; + + bsl::reference_wrapper assrwaz(bsl::ref(rwa)); + assrwaz = a; + assrwaz = c; + assrwaz = rwa; + + bsl::reference_wrapper assrwcaz(bsl::ref(rwca)); + assrwcaz = b; + assrwcaz = c; + assrwcaz = rwca; + assrwcaz = rwcb; + + ASSERT(copyrwa.get().localAddressOf() == a.localAddressOf()); + ASSERT(copyrwca.get().localAddressOf() == a.localAddressOf()); + ASSERT(copyrwcb.get().localAddressOf() == b.localAddressOf()); + ASSERT(copyrwaz.get().localAddressOf() == a.localAddressOf()); + ASSERT(copyrwcaz.get().localAddressOf() == a.localAddressOf()); + ASSERT(copyrwcbz.get().localAddressOf() == b.localAddressOf()); + + // These do not test much, but they seem preferable to "void(e)": + + ASSERT(rax.localAddressOf() == a.localAddressOf()); + ASSERT(rcax.localAddressOf() == a.localAddressOf()); + ASSERT(rcbx.localAddressOf() == b.localAddressOf()); + ASSERT(ray.localAddressOf() == a.localAddressOf()); + ASSERT(rcay.localAddressOf() == a.localAddressOf()); + ASSERT(rcby.localAddressOf() == b.localAddressOf()); + ASSERT(copyrwcazb.get().localAddressOf() == a.localAddressOf()); + ASSERT(copyrwcbzc.get().localAddressOf() == b.localAddressOf()); + } break; + default: { + fprintf(stderr, "WARNING: CASE `%d' NOT FOUND.\n", test); + testStatus = -1; + } + } + + if (testStatus > 0) { + fprintf(stderr, "Error, non-zero test status = %d.\n", testStatus); + } + return testStatus; +} + +// ---------------------------------------------------------------------------- +// Copyright 2013 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_removereference.h b/groups/bsl/bslmf/bslmf_removereference.h index 237f22af4a..70977f50b1 100644 --- a/groups/bsl/bslmf/bslmf_removereference.h +++ b/groups/bsl/bslmf/bslmf_removereference.h @@ -85,7 +85,7 @@ BSLS_IDENT("$Id: $") #include #if BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY -#include // 'std::remove_reference', 'std_remove_reference_t' +#include // 'std::remove_reference', 'std::remove_reference_t' #endif // ======================= diff --git a/groups/bsl/bslmf/bslmf_removereference.t.cpp b/groups/bsl/bslmf/bslmf_removereference.t.cpp index 9622203450..c4512802c1 100644 --- a/groups/bsl/bslmf/bslmf_removereference.t.cpp +++ b/groups/bsl/bslmf/bslmf_removereference.t.cpp @@ -235,7 +235,7 @@ int main(int argc, char *argv[]) // // Concerns: // 1. The meta functions `bsl::remove_reference` and - // `bsl::remove_reference_v` should be aliased to their standard + // `bsl::remove_reference_t` should be aliased to their standard // library analogs when the latter is available from the native // library. // diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.cpp new file mode 100644 index 0000000000..11406dca58 --- /dev/null +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.cpp @@ -0,0 +1,23 @@ +// bslmf_unwraprefdecay.cpp -*-C++-*- +#include + +#include +BSLS_IDENT("$Id$ $CSID$") + +#include // for testing only + +// ---------------------------------------------------------------------------- +// Copyright 2024 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.h b/groups/bsl/bslmf/bslmf_unwraprefdecay.h new file mode 100644 index 0000000000..c8be165d3b --- /dev/null +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.h @@ -0,0 +1,191 @@ +// bslmf_unwraprefdecay.h -*-C++-*- +#ifndef INCLUDED_BSLMF_UNWRAPREFDECAY +#define INCLUDED_BSLMF_UNWRAPREFDECAY + +#include +BSLS_IDENT("$Id: $") + +//@PURPOSE: Provide a meta-function to decay and unwrap reference wrappers. +// +//@CLASSES: +// bsl::unwrap_ref_decay: standard meta-function to unwrap decayed ref wrapper +// bsl::unwrap_ref_decay_t: alias to the return type of the meta-function +// +//@SEE_ALSO: bslmf_addreference +// +//@DESCRIPTION: This component defines a meta-function `bsl::unwrap_ref_decay` +// that may be used to unwrap a decayed (`bsl::decay`) `bsl::reference_wrapper` +// or a `std::reference_wrapper` of some type `U`, resulting in `U&`. In case +// the specified type template argument is not an specialization of either +// `reference_wrapper` (after decaying) the result is the type itself. +// +// `bsl::unwrap_ref_decay` meets the requirements of the `unwrap_ref_decay` +// template defined in the C++20 standard [meta.trans.other]. +// +///Usage +///----- +// In this section we show intended use of this component. +// +///Example 1: Unwrap Reference Wrapped Argument Types +/// - - - - - - - - - - - - - - - - - - - - - - - - - +// Suppose that we work in a programming environment where function argument +// types may be presented as is, or wrapped in a `bsl::reference_wrapper` or +// its `std` equivalent and we would like to create a member or local variable +// while obeying the request for reference-wrapping. So when the argument type +// decays into a reference wrapper we would like to use a reference to the +// wrapped type, and simply use the decayed variations of the unwrapped types. +// This is a use case for `bsl::unwrap_ref_decay`. +// +// First, we create types that may be the bases for reference-wrapped, and +// normal type parameters: +// ``` +// typedef bsl::reference_wrapper WrappedType; +// typedef int *NotWrappedType; +// ``` +// Next, we create types that represent possible function argument types: +// ``` +// typedef WrappedType WrappedTypeArray[5]; +// typedef WrappedType *WrappedTypePointer; +// typedef const WrappedType ConstWrappedType; +// typedef volatile WrappedType VolatileWrappedType; +// typedef const volatile WrappedType CvWrappedType; +// typedef WrappedType& WrappedTypeRef; +// typedef const WrappedType& ConstWrappedTypeRef; +// typedef volatile WrappedType& VolatileWrappedTypeRef; +// typedef const volatile WrappedType& CvWrappedTypeRef; +// +// typedef NotWrappedType NotWrappedTypeArray[5]; +// typedef NotWrappedType *NotWrappedTypePointer; +// typedef const NotWrappedType ConstNotWrappedType; +// typedef volatile NotWrappedType VolatileNotWrappedType; +// typedef const volatile NotWrappedType CvNotWrappedType; +// typedef NotWrappedType& NotWrappedTypeRef; +// typedef const NotWrappedType& ConstNotWrappedTypeRef; +// typedef volatile NotWrappedType& VolatileNotWrappedTypeRef; +// typedef const volatile NotWrappedType& CvNotWrappedTypeRef; +// ``` +// Finally we can verify and demonstrate how all these types turn into a +// decayed type, and only those that decay into a reference-wrapper type will +// become themselves references. Notice that an array of reference wrappers +// decays into a pointer to a wrapper, so it will not turn into a reference. +// ``` +// assert((true == bsl::is_same::type, +// WrappedType *>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// WrappedTypePointer>::value)); +// +// assert((true == bsl::is_same::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same::type, +// int *&>::value)); +// assert((true == bsl::is_same::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same::type, +// int *&>::value)); +// +// // Not wrapped types decay +// assert((true == bsl::is_same::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// ``` +// Note, that (when available) the `bsl::unwrap_ref_decay_t` avoids the +// `::type` suffix and `typename` prefix when we want to use the result of the +// `bsl::unwrap_ref_decay` meta-function in templates. + +#include + +#include + +#include +#include + +#if BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + #include // 'std::unwrap_reference', 'std::unwrap_reference_t' +#endif + + // ====================== + // struct uwrap_reference + // ====================== + +namespace bsl { + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY +using std::unwrap_ref_decay; +using std::unwrap_ref_decay_t; +#else + +/// This `struct` template implements the `unwrap_ref_decay` meta-function +/// defined in the C++20 standard [meta.trans.other], providing an alias, +/// `type`, that returns the result. `type` has the same type as the +/// (template parameter) `t_TYPE` unless `bsl::decay::type` is a +/// specialization of `bsl::reference_wrapper` or `std::reference_wrapper` +/// for a type U, in which case `type` shall be `U&`. +template +struct unwrap_ref_decay { + + /// This `typedef` is an alias to the template parameter `t_TYPE`. + typedef t_TYPE type; +}; + +#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES +template +using unwrap_ref_decay_t = typename unwrap_ref_decay::type; + // 'unwrap_ref_decay_t' is an alias to the return type of the + // 'bsl::unwrap_ref_decay' meta-function. Note, that the + // 'unwrap_ref_decay_t' avoids the '::type' suffix and 'typename' prefix + // when we want to use the result of the meta-function in templates. +#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + +#endif // else of BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + +} // close namespace bsl + +#endif + +// ---------------------------------------------------------------------------- +// Copyright 2024 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp new file mode 100644 index 0000000000..4614f97bd0 --- /dev/null +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -0,0 +1,439 @@ +// bslmf_unwraprefdecay.t.cpp -*-C++-*- +#include + +#include // for testing only + +#include +#include +#include + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY +#include // `std::unwrap_reference`, `std::unwrap_reference_t` +#endif + +#include // `printf` +#include // `atoi` + +using namespace BloombergLP; + +//============================================================================= +// TEST PLAN +//----------------------------------------------------------------------------- +// Overview +// -------- +// The component under test defines a meta-function `bsl::unwrap_reference` +// that unwraps a reference wrapper specialization `bsl::reference_wrapper` +// or `std::reference_wrapper` template `TYPE` argument by providing a +// `type` member with the type `U&`. If the specified `TYPE` is not a +// specialization of either reference wrapper the member `type` shall be +// `TYPE`. +// +// The component also defines an alias to the result type of the +// `bsl::unwrap_reference` meta-function. Thus, we need to ensure that the +// value returned by the meta-function is correct for each possible category of +// types. +// +// `bsl::unwrap_reference` and `bsl::unwrap_reference_t` should be aliased to +// `std::unwrap_reference` and `std::unwrap_reference_t`, respectively when the +// standard meta functions are available from the native library. +// +// ---------------------------------------------------------------------------- +// PUBLIC TYPES +// [ 1] bsl::unwrap_reference::type +// [ 1] bsl::unwrap_reference_t +// +// ---------------------------------------------------------------------------- +// [ 3] USAGE EXAMPLE +// [ 2] CONCERN: Aliased to standard types when available. + +// ============================================================================ +// STANDARD BSL ASSERT TEST FUNCTION +// ---------------------------------------------------------------------------- + +namespace { + +int testStatus = 0; + +void aSsErT(bool condition, const char *message, int line) +{ + if (condition) { + printf("Error " __FILE__ "(%d): %s (failed)\n", line, message); + + if (0 <= testStatus && testStatus <= 100) { + ++testStatus; + } + } +} + +} // close unnamed namespace + +// ============================================================================ +// STANDARD BSL TEST DRIVER MACRO ABBREVIATIONS +// ---------------------------------------------------------------------------- + +#define ASSERT BSLS_BSLTESTUTIL_ASSERT +#define ASSERTV BSLS_BSLTESTUTIL_ASSERTV + +#define LOOP_ASSERT BSLS_BSLTESTUTIL_LOOP_ASSERT +#define LOOP0_ASSERT BSLS_BSLTESTUTIL_LOOP0_ASSERT +#define LOOP1_ASSERT BSLS_BSLTESTUTIL_LOOP1_ASSERT +#define LOOP2_ASSERT BSLS_BSLTESTUTIL_LOOP2_ASSERT +#define LOOP3_ASSERT BSLS_BSLTESTUTIL_LOOP3_ASSERT +#define LOOP4_ASSERT BSLS_BSLTESTUTIL_LOOP4_ASSERT +#define LOOP5_ASSERT BSLS_BSLTESTUTIL_LOOP5_ASSERT +#define LOOP6_ASSERT BSLS_BSLTESTUTIL_LOOP6_ASSERT + +#define Q BSLS_BSLTESTUTIL_Q // Quote identifier literally. +#define P BSLS_BSLTESTUTIL_P // Print identifier and value. +#define P_ BSLS_BSLTESTUTIL_P_ // P(X) without '\n'. +#define T_ BSLS_BSLTESTUTIL_T_ // Print a tab (w/o newline). +#define L_ BSLS_BSLTESTUTIL_L_ // current Line number + +//============================================================================= +// TYPES FOR TESTING +//----------------------------------------------------------------------------- + +struct Struct {}; +class Class {}; +enum Enum {}; +union Union {}; + +//============================================================================= +// MAIN PROGRAM +//----------------------------------------------------------------------------- + +int main(int argc, char *argv[]) +{ + int test = argc > 1 ? atoi(argv[1]) : 0; + bool verbose = argc > 2; + bool veryVerbose = argc > 3; + bool veryVeryVerbose = argc > 4; + bool veryVeryVeryVerbose = argc > 5; + + (void)veryVerbose; // suppress warning + (void)veryVeryVerbose; // suppress warning + (void)veryVeryVeryVerbose; // suppress warning + + printf("TEST " __FILE__ " CASE %d\n", test); + + for(test=1;testStatus!=-1&&printf("TESTING: %d\n", test);++test) + switch (test) { case 0: + case 3: { + // -------------------------------------------------------------------- + // USAGE EXAMPLE + // + // Concerns: + // 1. The usage example provided in the component header file compiles, + // links, and runs as shown. + // + // Plan: + // 1. Incorporate usage example from header into test driver, remove + // leading comment characters, and replace `assert` with `ASSERT`. + // (C-1) + // + // Testing: + // USAGE EXAMPLE + // -------------------------------------------------------------------- + + if (verbose) puts("\nUSAGE EXAMPLE" + "\n============="); + +///Example 1: Unwrap Reference Wrapped Argument Types +/// - - - - - - - - - - - - - - - - - - - - - - - - - +// Suppose that we work in a programming environment where function argument +// types may be presented as is, or wrapped in a `bsl::reference_wrapper` or +// its `std` equivalent and we would like to create a member or local variable +// while obeying the request for reference-wrapping. So when the argument type +// decays into a reference wrapper we would like to use a reference to the +// wrapped type, and simply use the decayed variations of the unwrapped types. +// This is a use case for `bsl::unwrap_ref_decay`. +// +// First, we create types that may be the bases for reference-wrapped, and +// normal type parameters: +// ``` + typedef bsl::reference_wrapper WrappedType; + typedef int *NotWrappedType; +// ``` +// Next, we create types that represent possible function argument types: +// ``` + typedef WrappedType WrappedTypeArray[5]; + typedef WrappedType *WrappedTypePointer; + typedef const WrappedType ConstWrappedType; + typedef volatile WrappedType VolatileWrappedType; + typedef const volatile WrappedType CvWrappedType; + typedef WrappedType& WrappedTypeRef; + typedef const WrappedType& ConstWrappedTypeRef; + typedef volatile WrappedType& VolatileWrappedTypeRef; + typedef const volatile WrappedType& CvWrappedTypeRef; + + typedef NotWrappedType NotWrappedTypeArray[5]; + typedef NotWrappedType *NotWrappedTypePointer; + typedef const NotWrappedType ConstNotWrappedType; + typedef volatile NotWrappedType VolatileNotWrappedType; + typedef const volatile NotWrappedType CvNotWrappedType; + typedef NotWrappedType& NotWrappedTypeRef; + typedef const NotWrappedType& ConstNotWrappedTypeRef; + typedef volatile NotWrappedType& VolatileNotWrappedTypeRef; + typedef const volatile NotWrappedType& CvNotWrappedTypeRef; +// ``` +// Finally we can verify and demonstrate how all these types turn into a +// decayed type, and only those that decay into a reference-wrapper type will +// become themselves references. Notice that an array of reference wrappers +// decays into a pointer to a wrapper, so it will not turn into a reference. +// ``` + ASSERT((true == bsl::is_same::type, + WrappedType *>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + WrappedTypePointer>::value)); + + ASSERT((true == bsl::is_same::type, + int *&>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + int *&>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + int *&>::value)); + ASSERT((true == bsl::is_same::type, + int *&>::value)); + ASSERT((true == bsl::is_same::type, + int *&>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + int *&>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + int *&>::value)); + ASSERT((true == bsl::is_same::type, + int *&>::value)); + + ASSERT((true == bsl::is_same::type, + WrappedType *>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + WrappedTypePointer>::value)); + + // Not wrapped types decay + ASSERT((true == bsl::is_same::type, + NotWrappedType>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedType>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedType>::value)); + ASSERT((true == bsl::is_same::type, + NotWrappedType>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedType>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedType>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedType>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedType>::value)); +// ``` +// Note, that (when available) the `bsl::unwrap_ref_decay_t` avoids the +// `::type` suffix and `typename` prefix when we want to use the result of the +// `bsl::unwrap_ref_decay` meta-function in templates. + + } break; + case 2: { + // -------------------------------------------------------------------- + // ALIASED TO STANDARD META FUNCTIONS + // + // Concerns: + // 1. The meta functions `bsl::unwrap_ref_decay` and + // `bsl::unwrap_ref_decay_t` should be aliased to their standard + // library analogs when the latter is available from the native + // library. + // + // Plan: + // 1. If `BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY` is defined + // 1. Use `bsl::is_same` to compare `bsl::remove_ref_decay` to + // `std::remove_ref_decay` using a representative type. + // + // 2. Use `bsl::is_same` to compare `bsl::remove_reference_t` to + // `std::remove_reference_t` using a representative type. + // + // Testing: + // CONCERN: Aliased to standard types when available. + // -------------------------------------------------------------------- + + if (verbose) puts("\nALIASED TO STANDARD META FUNCTIONS" + "\n=================================="); + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + typedef int T; + + if (veryVerbose) puts("\tTesting `unwrap_ref_decay` `std` alias."); + + ASSERT((bsl::is_same, + std::unwrap_ref_decay >::value)); + + if (veryVerbose) puts("\tTesting `unwrap_ref_decay_t` `std` alias."); + + ASSERT((bsl::is_same, + std::unwrap_ref_decay_t >::value)); +#else + if (veryVerbose) put("\tSkipped: standard types aren't available"); +#endif + } break; + case 1: { + // -------------------------------------------------------------------- + // TESTING `bsl::unwrap_ref_decay::type` + // Ensure that the `typedef` `type` of `bsl::unwrap_ref_decay` + // instantiations having various (template parameter) `TYPE`s has the + // correct value. + // + // Concerns: + // 1. `unwrap_ref_decay::type` is `U&` for any template type argument + // that decays (`bsl::decay`) into `bsl::reference_wrapper` or + // `std::reference_wrapper`. + // + // 2. `unwrap_ref_decay` does not transform `TYPE` when `TYPE` does not + // decay into a reference-wrapper type. + // + // 3. `unwrap_ref_decay_t` represents the return type of + // `unwrap_ref_decay` meta-function. + // + // Plan: + // 1. Instantiate `bsl::unwrap_ref_decay` with various types and + // verify that the `type` member is initialized properly. (C-1,2) + // + // 2. Verify that `bsl::unwrap_ref_decay_t` has the same type as the + // return type of `bsl::unwrap_ref_decay`. (C-3) + // + // Testing: + // bsl::unwrap_ref_decay::type + // bsl::unwrap_ref_decay_t + // -------------------------------------------------------------------- + + if (verbose) puts("\nTESTING `bsl::unwrap_ref_decay::type`" + "\n====================================="); + + // C-1 + +#define ASSERT_UNWRAP_REF_(TYPE, RESULT) \ + ASSERT((true == bsl::is_same::type, \ + RESULT>::value)) + +#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + #define ASSERT_UNWRAP_REF_T(TYPE, RESULT) \ + ASSERT((true == bsl::is_same, \ + RESULT>::value)) + + #define ASSERT_UNWRAP_REF(TYPE, RESULT) \ + ASSERT_UNWRAP_REF_(TYPE, RESULT); ASSERT_UNWRAP_REF_T(TYPE, RESULT) +#else // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + #define ASSERT_UNWRAP_REF ASSERT_UNWRAP_REF_ +#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + + ASSERT_UNWRAP_REF(void*, void*); + + ASSERT_UNWRAP_REF(int&, int); + ASSERT_UNWRAP_REF(const int&, int); + ASSERT_UNWRAP_REF(const volatile int&, int); + + typedef int IntArray[5]; + ASSERT_UNWRAP_REF(IntArray, int*); + ASSERT_UNWRAP_REF(IntArray&, int*); + + typedef void FuncType(); + ASSERT_UNWRAP_REF(FuncType, FuncType*); + ASSERT_UNWRAP_REF(FuncType&, FuncType*); + + // Arrays decay into pointers so the wrapper should not be unwrapped + typedef bsl::reference_wrapper WrappedType; + ASSERT_UNWRAP_REF(WrappedType[], WrappedType*); + + ASSERT_UNWRAP_REF(FuncType, FuncType*); + ASSERT_UNWRAP_REF(Enum, Enum); + ASSERT_UNWRAP_REF(Struct, Struct); + ASSERT_UNWRAP_REF(Union, Union); + ASSERT_UNWRAP_REF(Class, Class); + + ASSERT_UNWRAP_REF(int Class::*, int Class::*); + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + #define ASSERT_UNWRAP_REF_WRAPPED(TYPE, RESULT) \ + ASSERT_UNWRAP_REF(bsl::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(std::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(bsl::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(std::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(const bsl::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(const std::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(const bsl::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(const std::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(volatile bsl::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(volatile std::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(volatile bsl::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(volatile std::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(const volatile bsl::reference_wrapper, \ + RESULT); \ + ASSERT_UNWRAP_REF(const volatile std::reference_wrapper, \ + RESULT); \ + ASSERT_UNWRAP_REF(const volatile bsl::reference_wrapper&, \ + RESULT); \ + ASSERT_UNWRAP_REF(const volatile std::reference_wrapper&, \ + RESULT) +#else + #define ASSERT_UNWRAP_REF_WRAPPED(TYPE, RESULT) \ + ASSERT_UNWRAP_REF(bsl::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(bsl::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(const bsl::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(const bsl::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(volatile bsl::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(volatile bsl::reference_wrapper&, RESULT); \ + ASSERT_UNWRAP_REF(const volatile bsl::reference_wrapper, \ + RESULT); \ + ASSERT_UNWRAP_REF(const volatile bsl::reference_wrapper&, \ + RESULT) +#endif + + ASSERT_UNWRAP_REF_WRAPPED(void*, void*&); + ASSERT_UNWRAP_REF_WRAPPED(int, int&); + ASSERT_UNWRAP_REF_WRAPPED(int&, int&); + ASSERT_UNWRAP_REF_WRAPPED(const int&, const int&); + ASSERT_UNWRAP_REF_WRAPPED(const volatile int, const volatile int&); + ASSERT_UNWRAP_REF_WRAPPED(Enum, Enum&); + ASSERT_UNWRAP_REF_WRAPPED(Struct, Struct&); + ASSERT_UNWRAP_REF_WRAPPED(Union, Union&); + ASSERT_UNWRAP_REF_WRAPPED(Class, Class&); + + ASSERT_UNWRAP_REF_WRAPPED(int Class::*, int Class::*&); + + } break; + default: { + fprintf(stderr, "WARNING: CASE `%d' NOT FOUND.\n", test); + testStatus = -1; + } + } + + if (testStatus > 0) { + fprintf(stderr, "Error, non-zero test status = %d.\n", testStatus); + } + + return testStatus; +} + +// ---------------------------------------------------------------------------- +// Copyright 2024 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.cpp b/groups/bsl/bslmf/bslmf_unwrapreference.cpp new file mode 100644 index 0000000000..5175102278 --- /dev/null +++ b/groups/bsl/bslmf/bslmf_unwrapreference.cpp @@ -0,0 +1,23 @@ +// bslmf_unwrapreference.cpp -*-C++-*- +#include + +#include +BSLS_IDENT("$Id$ $CSID$") + +#include // for testing only + +// ---------------------------------------------------------------------------- +// Copyright 2024 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.h b/groups/bsl/bslmf/bslmf_unwrapreference.h new file mode 100644 index 0000000000..f473a825cf --- /dev/null +++ b/groups/bsl/bslmf/bslmf_unwrapreference.h @@ -0,0 +1,131 @@ +// bslmf_unwrapreference.h -*-C++-*- +#ifndef INCLUDED_BSLMF_UNWRAPREFERENCE +#define INCLUDED_BSLMF_UNWRAPREFERENCE + +#include +BSLS_IDENT("$Id: $") + +//@PURPOSE: Provide a meta-function to unwrap reference wrappers. +// +//@CLASSES: +// bsl::unwrap_reference: standard meta-function to unwrap reference wrappers +// bsl::unwrap_reference_t: alias to the return type of the meta-function +// +//@SEE_ALSO: bslmf_addreference +// +//@DESCRIPTION: This component defines a meta-function `bsl::unwrap_reference` +// that may be used to unwrap a `bsl::reference_wrapper` or a +// `std::reference_wrapper` of some type `U`, resulting in `U&`. In case the +// specified type template argument is not an specialization of either +// `reference_wrapper` the result is the type itself. +// +// `bsl::unwrap_reference` meets the requirements of the `unwrap_reference` +// template defined in the C++20 standard [meta.trans.other]. +// +///Usage +///----- +// In this section we show intended use of this component. +// +///Example 1: Unwrap Reference Wrapped Types +///- - - - - - - - - - - - - - - - - - - - - +// Suppose that we work in a programming environment where types may be +// presented wrapped in a `bsl::reference_wrapper` or its `std` equivalent. We +// would like to use a reference to the wrapped type, but use unwrapped types +// as they are. This is the exact use case for `bsl::unwrap_reference`. +// +// First, we create types that represent both reference-wrapped, and normal +// type parameters: +// ``` +// typedef bsl::reference_wrapper WrappedType; +// typedef int *NotWrappedType; +// ``` +// Next, we create types that are references if they were wrapped: +// ``` +// typedef bsl::unwrap_reference::type UnwrappedWrapped; +// typedef bsl::unwrap_reference::type UnwrappedNotWrapped; +// ``` +// Finally we can verify that the wrapped type became a reference, while the +// other type is unchanged: +// ``` +// assert((true == bsl::is_same::value)); +// assert((true == bsl::is_same::value)); +// ``` +// Note, that (when available) the `bsl::unwrap_reference_t` avoids the +// `::type` suffix and `typename` prefix when we want to use the result of the +// `bsl::unwrap_reference` meta-function in templates. + +#include + +#include + +#include +#include + +#if BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + #include // 'std::unwrap_reference', 'std::unwrap_reference_t' +#endif + + // ====================== + // struct uwrap_reference + // ====================== + +namespace bsl { + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY +using std::unwrap_reference; +using std::unwrap_reference_t; +#else + +/// This `struct` template implements the `unwrap_reference` meta-function +/// defined in the C++20 standard [meta.trans.other], providing an alias, +/// `type`, that returns the result. `type` has the same type as the +/// (template parameter) `t_TYPE` unless `t_TYPE` is a specialization of +/// `bsl::reference_wrapper` or `std::reference_wrapper` for a type U, in +/// which case `type` shall be `U&`. +template +struct unwrap_reference { + + /// This `typedef` is an alias to the template parameter `t_TYPE`. + typedef t_TYPE type; +}; + +/// This partial specialization of `bsl::remove_reference`, for when the +/// template parameter `t_TYPE` is a `bsl::reference_wrapper`, provides a +/// `typedef`, `type`, that is `t_TYPE::type`. +template +struct remove_reference { + + typedef t_TYPE type; +}; + +#if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES) +// ALIASES +template +using unwrap_reference_t = typename unwrap_reference::type; + // 'unwrap_reference_t' is an alias to the return type of the + // 'bsl::unwrap_reference' meta-function. Note, that the + // 'unwrap_reference_t' avoids the '::type' suffix and 'typename' prefix + // when we want to use the result of the meta-function in templates. +#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + +#endif // else of BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + +} // close namespace bsl + +#endif + +// ---------------------------------------------------------------------------- +// Copyright 2024 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp new file mode 100644 index 0000000000..b3efae68b2 --- /dev/null +++ b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp @@ -0,0 +1,314 @@ +// bslmf_unwrapreference.t.cpp -*-C++-*- +#include + +#include // for testing only + +#include +#include +#include + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY +#include // `std::unwrap_reference`, `std::unwrap_reference_t` +#endif + +#include // `printf` +#include // `atoi` + +using namespace BloombergLP; + +//============================================================================= +// TEST PLAN +//----------------------------------------------------------------------------- +// Overview +// -------- +// The component under test defines a meta-function `bsl::unwrap_reference` +// that unwraps a reference wrapper specialization `bsl::reference_wrapper` +// or `std::reference_wrapper` template `TYPE` argument by providing a +// `type` member with the type `U&`. If the specified `TYPE` is not a +// specialization of either reference wrapper the member `type` shall be +// `TYPE`. +// +// The component also defines an alias to the result type of the +// `bsl::unwrap_reference` meta-function. Thus, we need to ensure that the +// value returned by the meta-function is correct for each possible category of +// types. +// +// `bsl::unwrap_reference` and `bsl::unwrap_reference_t` should be aliased to +// `std::unwrap_reference` and `std::unwrap_reference_t`, respectively when the +// standard meta functions are available from the native library. +// +// ---------------------------------------------------------------------------- +// PUBLIC TYPES +// [ 1] bsl::unwrap_reference::type +// [ 1] bsl::unwrap_reference_t +// +// ---------------------------------------------------------------------------- +// [ 3] USAGE EXAMPLE +// [ 2] CONCERN: Aliased to standard types when available. + +// ============================================================================ +// STANDARD BSL ASSERT TEST FUNCTION +// ---------------------------------------------------------------------------- + +namespace { + +int testStatus = 0; + +void aSsErT(bool condition, const char *message, int line) +{ + if (condition) { + printf("Error " __FILE__ "(%d): %s (failed)\n", line, message); + + if (0 <= testStatus && testStatus <= 100) { + ++testStatus; + } + } +} + +} // close unnamed namespace + +// ============================================================================ +// STANDARD BSL TEST DRIVER MACRO ABBREVIATIONS +// ---------------------------------------------------------------------------- + +#define ASSERT BSLS_BSLTESTUTIL_ASSERT +#define ASSERTV BSLS_BSLTESTUTIL_ASSERTV + +#define LOOP_ASSERT BSLS_BSLTESTUTIL_LOOP_ASSERT +#define LOOP0_ASSERT BSLS_BSLTESTUTIL_LOOP0_ASSERT +#define LOOP1_ASSERT BSLS_BSLTESTUTIL_LOOP1_ASSERT +#define LOOP2_ASSERT BSLS_BSLTESTUTIL_LOOP2_ASSERT +#define LOOP3_ASSERT BSLS_BSLTESTUTIL_LOOP3_ASSERT +#define LOOP4_ASSERT BSLS_BSLTESTUTIL_LOOP4_ASSERT +#define LOOP5_ASSERT BSLS_BSLTESTUTIL_LOOP5_ASSERT +#define LOOP6_ASSERT BSLS_BSLTESTUTIL_LOOP6_ASSERT + +#define Q BSLS_BSLTESTUTIL_Q // Quote identifier literally. +#define P BSLS_BSLTESTUTIL_P // Print identifier and value. +#define P_ BSLS_BSLTESTUTIL_P_ // P(X) without '\n'. +#define T_ BSLS_BSLTESTUTIL_T_ // Print a tab (w/o newline). +#define L_ BSLS_BSLTESTUTIL_L_ // current Line number + +//============================================================================= +// TYPES FOR TESTING +//----------------------------------------------------------------------------- + +struct Struct {}; +class Class {}; +enum Enum {}; +union Union {}; + +//============================================================================= +// MAIN PROGRAM +//----------------------------------------------------------------------------- + +int main(int argc, char *argv[]) +{ + int test = argc > 1 ? atoi(argv[1]) : 0; + bool verbose = argc > 2; + bool veryVerbose = argc > 3; + bool veryVeryVerbose = argc > 4; + bool veryVeryVeryVerbose = argc > 5; + + (void)veryVerbose; // suppress warning + (void)veryVeryVerbose; // suppress warning + (void)veryVeryVeryVerbose; // suppress warning + + printf("TEST " __FILE__ " CASE %d\n", test); + + switch (test) { case 0: + case 3: { + // -------------------------------------------------------------------- + // USAGE EXAMPLE + // + // Concerns: + // 1. The usage example provided in the component header file compiles, + // links, and runs as shown. + // + // Plan: + // 1. Incorporate usage example from header into test driver, remove + // leading comment characters, and replace `assert` with `ASSERT`. + // (C-1) + // + // Testing: + // USAGE EXAMPLE + // -------------------------------------------------------------------- + + if (verbose) puts("\nUSAGE EXAMPLE" + "\n============="); + +///Example 1: Unwrap Reference Wrapped Types +///- - - - - - - - - - - - - - - - - - - - - +// Suppose that we work in a programming environment where types may be +// presented wrapped in a `bsl::reference_wrapper` or its `std` equivalent. We +// would like to use a reference to the wrapped type, but use unwrapped types +// as they are. This is the exact use case for `bsl::unwrap_reference`. +// +// First, we create types that represent both reference-wrapped, and normal +// type parameters: +// ``` + typedef bsl::reference_wrapper WrappedType; + typedef int *NotWrappedType; +// ``` +// Next, we create types that are references if they were wrapped: +// ``` + typedef bsl::unwrap_reference::type UnwrappedWrapped; + typedef bsl::unwrap_reference::type UnwrappedNotWrapped; +// ``` +// Finally we can verify that the wrapped type became a reference, while the +// other type is unchanged: +// ``` + ASSERT((true == bsl::is_same::value)); + ASSERT((true == bsl::is_same::value)); +// ``` +// Note, that (when available) the `bsl::unwrap_reference_t` avoids the +// `::type` suffix and `typename` prefix when we want to use the result of the +// `bsl::unwrap_reference` meta-function in templates. + } break; + case 2: { + // -------------------------------------------------------------------- + // ALIASED TO STANDARD META FUNCTIONS + // + // Concerns: + // 1. The meta functions `bsl::unwrap_reference` and + // `bsl::unwrap_reference_t` should be aliased to their standard + // library analogs when the latter is available from the native + // library. + // + // Plan: + // 1. If `BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY` is defined + // 1. Use `bsl::is_same` to compare `bsl::unwrap_reference` to + // `std::unwrap_reference` using a representative type. + // + // 2. Use `bsl::is_same` to compare `bsl::unwrap_reference_t` to + // `std::unwrap_reference_t` using a representative type. + // + // Testing: + // CONCERN: Aliased to standard types when available. + // -------------------------------------------------------------------- + + if (verbose) puts("\nALIASED TO STANDARD META FUNCTIONS" + "\n=================================="); + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + typedef int T; + + if (veryVerbose) puts("\tTesting `unwrap_reference` `std` alias."); + + ASSERT((bsl::is_same, + std::unwrap_reference >::value)); + + if (veryVerbose) puts("\tTesting `unwrap_reference_t` `std` alias."); + + ASSERT((bsl::is_same, + std::unwrap_reference_t >::value)); +#else + if (veryVerbose) put("\tSkipped: standard types aren't available"); +#endif + } break; + case 1: { + // -------------------------------------------------------------------- + // TESTING `bsl::unwrap_reference::type` + // Ensure that the `typedef` `type` of `bsl::unwrap_reference` + // instantiations having various (template parameter) `TYPE`s has the + // correct value. + // + // Concerns: + // 1. `unwrap_reference::type` is `U&` for any + // `bsl::reference_wrapper` or `std::reference_wrapper`. + // + // 2. `unwrap_reference` does not transform `TYPE` when `TYPE` is not a + // reference-wrapper type. + // + // 3. `unwrap_reference_t` represents the return type of + // `unwrap_reference` meta-function. + // + // Plan: + // 1. Instantiate `bsl::unwrap_reference` with various types and + // verify that the `type` member is initialized properly. (C-1,2) + // + // 2. Verify that `bsl::unwrap_reference_t` has the same type as the + // return type of `bsl::unwrap_reference`. (C-3) + // + // Testing: + // bsl::unwrap_reference::type + // bsl::unwrap_reference_t + // -------------------------------------------------------------------- + + if (verbose) puts("\nTESTING `bsl::unwrap_reference::type`" + "\n====================================="); + + // C-1 + +#define ASSERT_UNWRAP_REF_(TYPE, RESULT) \ + ASSERT((true == bsl::is_same::type, \ + RESULT>::value)) + +#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + #define ASSERT_UNWRAP_REF_T(TYPE, RESULT) \ + ASSERT((true == bsl::is_same, \ + RESULT>::value)) + + #define ASSERT_UNWRAP_REF(TYPE, RESULT) \ + ASSERT_UNWRAP_REF_(TYPE, RESULT); ASSERT_UNWRAP_REF_T(TYPE, RESULT) +#else // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + #define ASSERT_UNWRAP_REF ASSERT_UNWRAP_REF_ +#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES + + ASSERT_UNWRAP_REF(void*, void*); + ASSERT_UNWRAP_REF(int&, int&); + ASSERT_UNWRAP_REF(Enum, Enum); + ASSERT_UNWRAP_REF(Struct, Struct); + ASSERT_UNWRAP_REF(Union, Union); + ASSERT_UNWRAP_REF(Class, Class); + + ASSERT_UNWRAP_REF(int Class::*, int Class::*); + +#ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY + #define ASSERT_UNWRAP_REF_WRAPPED(TYPE, RESULT) \ + ASSERT_UNWRAP_REF(bsl::reference_wrapper, RESULT); \ + ASSERT_UNWRAP_REF(std::reference_wrapper, RESULT) +#else + #define ASSERT_UNWRAP_REF_WRAPPED(TYPE, RESULT) \ + ASSERT_UNWRAP_REF(bsl::reference_wrapper, RESULT) +#endif + + ASSERT_UNWRAP_REF_WRAPPED(void*, void*&); + ASSERT_UNWRAP_REF_WRAPPED(int, int&); + ASSERT_UNWRAP_REF_WRAPPED(int&, int&); + ASSERT_UNWRAP_REF_WRAPPED(Enum, Enum&); + ASSERT_UNWRAP_REF_WRAPPED(Struct, Struct&); + ASSERT_UNWRAP_REF_WRAPPED(Union, Union&); + ASSERT_UNWRAP_REF_WRAPPED(Class, Class&); + + ASSERT_UNWRAP_REF_WRAPPED(int Class::*, int Class::*&); + + } break; + default: { + fprintf(stderr, "WARNING: CASE `%d' NOT FOUND.\n", test); + testStatus = -1; + } + } + + if (testStatus > 0) { + fprintf(stderr, "Error, non-zero test status = %d.\n", testStatus); + } + + return testStatus; +} + +// ---------------------------------------------------------------------------- +// Copyright 2024 Bloomberg Finance L.P. +// +// 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. +// ----------------------------- END-OF-FILE ---------------------------------- diff --git a/groups/bsl/bslmf/package/bslmf.mem b/groups/bsl/bslmf/package/bslmf.mem index a067b4e468..82119d9eb4 100644 --- a/groups/bsl/bslmf/package/bslmf.mem +++ b/groups/bsl/bslmf/package/bslmf.mem @@ -75,6 +75,7 @@ bslmf_nestedtraitdeclaration bslmf_nil bslmf_nthparameter bslmf_nthparameter_cpp03 +bslmf_referencewrapper bslmf_removeconst bslmf_removecv bslmf_removecvq @@ -89,6 +90,8 @@ bslmf_switch bslmf_tag bslmf_typeidentity bslmf_typelist +bslmf_unwraprefdecay +bslmf_unwrapreference bslmf_usesallocator bslmf_usesallocatorargt bslmf_util diff --git a/groups/bsl/bslstl/bslstl_referencewrapper.h b/groups/bsl/bslstl/bslstl_referencewrapper.h index 9d977fc0b8..1ccbb3e402 100644 --- a/groups/bsl/bslstl/bslstl_referencewrapper.h +++ b/groups/bsl/bslstl/bslstl_referencewrapper.h @@ -12,267 +12,23 @@ BSLS_IDENT("$Id: $") // //@CANONICAL_HEADER: bsl_functional.h // -//@DESCRIPTION: This component provides `bsl::reference_wrapper`, a reduced -// implementation of the standard C++2011 template of the same name, which -// simply wraps a reference into a copyable, assignable object to allow it to -// be stored in a place that cannot normally hold a reference, such as a -// standard container. Because a reference wrapper is convertible to its -// contained reference type, it can be passed to functions that take such a -// reference. -// -// This component also provides the (free) helper functions `bsl::ref` and -// `bsl::cref` that may be used to generate `reference_wrapper` objects more -// concisely than with the constructor. -// -// NOTE: This component is a partial implementation of the standard class, -// omitting support for use as a function object, and is in any case of -// limited usefulness in a pure C++98 environment. -// -///Usage -///----- -// This section illustrates intended use of this component. -// -///Example 1: Sorted References -/// - - - - - - - - - - - - - - -// Let us suppose that we wish to handle objects that will be passed to a -// comparison function expecting references to the objects. Let us suppose -// further that these objects are large enough that we would not wish to move -// them around bodily as they are sorted. Note that plausible examples of uses -// for this component are limited in freestanding C++98. -// -// First, let us define the large-object type: -// ``` -// struct Canary { -// static const int s_size = 1000; -// Canary *d_values[s_size]; -// Canary(); -// }; -// -// Canary::Canary() -// { -// for (int i = 0; i < s_size; ++i) { -// d_values[i] = this; -// } -// } -// ``` -// Next, we define the comparison function: -// ``` -// bool operator<(Canary const& a, Canary const& b) -// { -// return a.d_values[0] < b.d_values[0]; -// } -// ``` -// Finally, we define a generic function to sort two items: -// ``` -// template -// void sortTwoItems(T& a, T& b) -// { -// if (b < a) { -// T tmp(a); -// a = b; -// b = tmp; -// } -// } -// ``` -// We can call `sortTwoItems` on wrappers representing `Canary` objects -// without need to move actual, large `Canary` objects about. In the call to -// `sortTwoItems`, below, the `operator=` used in it is that of -// `bsl::reference_wrapper`, but the `operator<` used is the one -// declared for `Canary&` arguments. All of the conversions needed are -// applied implicitly: -// ``` -// Canary canaries[2]; -// bsl::reference_wrapper canaryA = bsl::ref(canaries[1]); -// bsl::reference_wrapper canaryB = bsl::ref(canaries[0]); -// sortTwoItems(canaryA, canaryB); -// -// assert(&canaryA.get() == canaries); -// assert(&canaryB.get() == canaries + 1); -// ``` +//@DESCRIPTION: This component just includes `` due +// to backwards compatibility. See `bslmf_referencewrapper` for more +// information. #include -#include -#include - -#include -#include -#include // for BloombergLP::bsls::Util::addressOf - -#ifdef BSLS_LIBRARYFEATURES_HAS_CPP11_BASELINE_LIBRARY -#include +#include -#define BSLSTL_REFRENCEWRAPPER_IS_ALIASED - -namespace bsl { -using std::cref; -using std::ref; -using std::reference_wrapper; -} // close enterprise namespace +#ifdef BSLMF_REFERENCEWRAPPER_IS_ALIASED + // Typo in the name is intentional for backwards compatibility + #define BSLSTL_REFRENCEWRAPPER_IS_ALIASED #endif -#ifndef BSLSTL_REFRENCEWRAPPER_IS_ALIASED -namespace bsl { - - // ======================= - // class reference_wrapper - // ======================= - -/// This class is a wrapper that encapsulates an object reference, enabling -/// operations not possible on actual references, including assignment, -/// copying, and storage in standard containers. When stored in a -/// container, it enables functions defined to operate on references to the -/// type represented to be called on the container elements. -template -class reference_wrapper { - - private: - // DATA - T *d_represented_p; // the represented object (not owned) - - public: - // TYPES - typedef T type; - - // CREATORS - - /// Create a reference wrapper representing the specified `object`. - reference_wrapper(T& object) BSLS_KEYWORD_NOEXCEPT; // IMPLICIT - - //! reference_wrapper(const reference_wrapper& original) = default; - // Create a reference wrapper referring to the same object as the - // specified 'original'. - - //! ~reference_wrapper() = default; - // Destroy this object. - - // MANIPULATORS - //! reference_wrapper& operator=(const reference_wrapper& rhs) = default; - // Assign this object to refer to the same object as the specified - // 'rhs', and return '*this'. - - // ACCESSORS - - /// Return a reference to the object that `*this` represents. - T& get() const BSLS_KEYWORD_NOEXCEPT; - - /// Return a reference to the object that `*this` represents. - operator T&() const BSLS_KEYWORD_NOEXCEPT; -}; - -// FREE FUNCTIONS - -/// Return a reference wrapper representing a `const` view of the specified -/// `object`. -template -reference_wrapper cref(const T& object) BSLS_KEYWORD_NOEXCEPT; - -template -reference_wrapper cref(reference_wrapper original) - BSLS_KEYWORD_NOEXCEPT; - // Return a reference wrapper representing a 'const' view of the same - // object as the specified 'original'. - -/// Return a reference wrapper that represents the specified `object`. -template -reference_wrapper ref(T& object) BSLS_KEYWORD_NOEXCEPT; - -/// Return a reference wrapper that represents the same object as the -/// specified `original`. -template -reference_wrapper ref(reference_wrapper original) BSLS_KEYWORD_NOEXCEPT; - -} // close namespace bsl - -// ============================================================================ -// INLINE DEFINITIONS -// ============================================================================ - - // ----------------------- - // class reference_wrapper - // ----------------------- - -// CREATORS -template -inline -bsl::reference_wrapper::reference_wrapper(T& object) BSLS_KEYWORD_NOEXCEPT - : d_represented_p(BloombergLP::bsls::Util::addressOf(object)) -{ -} - -// ACCESSORS -template -inline -T& bsl::reference_wrapper::get() const BSLS_KEYWORD_NOEXCEPT -{ - return *d_represented_p; -} - -template -inline -bsl::reference_wrapper::operator T&() const BSLS_KEYWORD_NOEXCEPT -{ - return *d_represented_p; -} - -// FREE FUNCTIONS -template -inline -bsl::reference_wrapper bsl::cref(const T& object) - BSLS_KEYWORD_NOEXCEPT -{ - return reference_wrapper(object); -} - -template -inline -bsl::reference_wrapper bsl::cref(bsl::reference_wrapper original) - BSLS_KEYWORD_NOEXCEPT -{ - return cref(original.get()); -} - -template -inline -bsl::reference_wrapper bsl::ref(T& object) BSLS_KEYWORD_NOEXCEPT -{ - return reference_wrapper(object); -} - -template -inline -bsl::reference_wrapper bsl::ref(bsl::reference_wrapper original) - BSLS_KEYWORD_NOEXCEPT -{ - return ref(original.get()); -} - -// TRAITS - -namespace BloombergLP { -namespace bslmf { - -template -struct IsBitwiseMoveable > : bsl::true_type { }; - -} // close namespace bslmf -} // close enterprise namespace - -#endif // BSLSTL_REFRENCEWRAPPER_IS_ALIASED - -namespace BloombergLP { -namespace bslmf { - -template -struct IsReferenceWrapper > : bsl::true_type { }; - -} // close namespace bslmf -} // close enterprise namespace - #endif // ---------------------------------------------------------------------------- -// Copyright 2013 Bloomberg Finance L.P. +// Copyright 2024 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp b/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp index 12ccc39614..e99d9f9581 100644 --- a/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp +++ b/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp @@ -1,14 +1,8 @@ // bslstl_referencewrapper.t.cpp -*-C++-*- #include -#include -#include - #include -#include -#include -#include #include #include @@ -17,25 +11,18 @@ // ---------------------------------------------------------------------------- // Overview // -------- -// The component under test is fully specified by the standard, verifiable by -// inspection. Therefore, testing only exercises basic uses to ensure template -// specializations may be instantiated successfully. +// The component under test is a legacy, backwards compatibility component that +// simply `#include`s ``. In this test driver we +// simply verify that the names in `bsl` exist, and that the +// `BSLSTL_REFRENCEWRAPPER_IS_ALIASED` macro is defined when expected. // // ---------------------------------------------------------------------------- -// TESTING INSTANTIATIONS AND BASIC FUNCTIONALITY -// [ 1] reference_wrapper(T&); -// [ 1] reference_wrapper(const reference_wrapper&); -// [ 1] reference_wrapper& operator=(reference_wrapper&); -// [ 1] operator T&() const; -// [ 1] T& get() const; -// [ 3] operator()(...) const; +// [ 1] reference_wrapper // [ 1] reference_wrapper cref(const T&); // [ 1] reference_wrapper cref(reference_wrapper); // [ 1] reference_wrapper ref(T&); // [ 1] reference_wrapper ref(reference_wrapper); -// ---------------------------------------------------------------------------- -// [ 4] USAGE EXAMPLE -// [ 2] TYPE TRAITS +// [ 1] BSLSTL_REFRENCEWRAPPER_IS_ALIASED // ============================================================================ // STANDARD BSL ASSERT TEST FUNCTION @@ -80,101 +67,6 @@ void aSsErT(bool condition, const char *message, int line) #define T_ BSLS_BSLTESTUTIL_T_ // Print a tab (w/o newline). #define L_ BSLS_BSLTESTUTIL_L_ // current Line number -// ============================================================================ -// GLOBAL TYPEDEFS/CONSTANTS FOR TESTING -// ---------------------------------------------------------------------------- - -struct Callable { - void operator()() { } - int operator()(int) { return 42; } - int operator()(int) const { return -42; } -}; - -/// Test class that is not bitwise moveable -struct NonBitwiseDummy { - int d_data; - - explicit NonBitwiseDummy(int v = 0) : d_data(v) { } - NonBitwiseDummy(const NonBitwiseDummy& rhs) : d_data(rhs.d_data) {} -}; - -// ============================================================================ -// TEST FACILITIES -// ---------------------------------------------------------------------------- - -struct Dummy { - void operator&(); - const Dummy *localAddressOf() const { return this; } -}; -/// These functions are used solely to verify that a `reference_wrapper` can -/// be passed to a function expecting an actual reference. -bool isConst(Dummy&) { return false; } -bool isConst(const Dummy&) { return true; } - -// ============================================================================ -// USAGE EXAMPLE CLASSES AND FUNCTIONS -// ---------------------------------------------------------------------------- - -// Disable specific bde_verify warnings where practice of usage example may -// differ. - -// BDE_VERIFY pragma: push -// BDE_VERIFY pragma: -FD01 // Function needs contract, we probably should fix -// BDE_VERIFY pragma: -IND01 // Code is aligned as-if following a `//` comment - - -namespace TEST_CASE_USAGE { - -///Usage -///----- -// This section illustrates intended use of this component. -// -///Example 1: Sorted References -/// - - - - - - - - - - - - - - -// Let us suppose that we wish to handle objects that will be passed to a -// comparison function expecting references to the objects. Let us suppose -// further that these objects are large enough that we would not wish to move -// them around bodily as they are sorted. Note that plausible examples of uses -// for this component are limited in freestanding C++98. -// -// First, let us define the large-object type: -// ``` - struct Canary { - static const int s_size = 1000; - Canary *d_values[s_size]; - Canary(); - }; -// ``` - Canary::Canary() - { - for (int i = 0; i < s_size; ++i) { - d_values[i] = this; - } - } -// ``` -// Next, we define the comparison function: -// ``` - bool operator<(Canary const& a, Canary const& b) - { - return a.d_values[0] < b.d_values[0]; - } -// ``` -// Finally, we define a generic function to sort two items: -// ``` - template - void sortTwoItems(T& a, T& b) - { - if (b < a) { - T tmp(a); - a = b; - b = tmp; - } - } -// ``` -} // close namespace TEST_CASE_USAGE - -// BDE_VERIFY pragma: pop - // ============================================================================ // MAIN PROGRAM // ---------------------------------------------------------------------------- @@ -183,304 +75,67 @@ int main(int argc, char *argv[]) { int test = argc > 1 ? atoi(argv[1]) : 0; bool verbose = argc > 2; - bool veryVerbose = argc > 3; - bool veryVeryVerbose = argc > 4; - bool veryVeryVeryVerbose = argc > 5; - - (void) veryVerbose; // unused variable warning - (void) veryVeryVerbose; // unused variable warning - (void)veryVeryVeryVerbose; // unused variable warning + bool veryVerbose = argc > 3; (void)veryVerbose; + bool veryVeryVerbose = argc > 4; (void)veryVeryVerbose; printf("TEST " __FILE__ " CASE %d\n", test); switch (test) { case 0: - case 4: { - // -------------------------------------------------------------------- - // USAGE EXAMPLE - // Extracted from component header file. - // - // Concerns: - // 1. The usage example in the component header file compiles, links, - // and runs as shown. - // - // Plan: - // 1. Incorporate usage example from header into test driver, remove - // leading comment characters, and replace `assert` with `ASSERT`. - // (C-1) - // - // Testing: - // USAGE EXAMPLE - // -------------------------------------------------------------------- - - if (verbose) { - printf("\nUSAGE EXAMPLE" - "\n=============\n"); - } - - using namespace TEST_CASE_USAGE; - -// Disable specific bde_verify warnings where practice of usage example may -// differ. - -// BDE_VERIFY pragma: push -// BDE_VERIFY pragma: -FD01 // Function needs contract, we probably should fix -// BDE_VERIFY pragma: -IND01 // Code is aligned as-if following a `//` comment - -// ``` -// We can call `sortTwoItems` on wrappers representing `Canary` objects -// without need to move actual, large `Canary` objects about. In the call to -// `sortTwoItems`, below, the `operator=` used in it is that of -// `bsl::reference_wrapper`, but the `operator<` used is the one -// declared for `Canary&` arguments. All of the conversions needed are -// applied implicitly: -// ``` - Canary canaries[2]; - - bsl::reference_wrapper canaryA = bsl::ref(canaries[1]); - bsl::reference_wrapper canaryB = bsl::ref(canaries[0]); - sortTwoItems(canaryA, canaryB); -// - ASSERT(&canaryA.get() == canaries); - ASSERT(&canaryB.get() == canaries + 1); -// ``` - -// BDE_VERIFY pragma: pop - - } break; - case 3: { - // -------------------------------------------------------------------- - // TESTING CALLABLE - // Testing that bsl::reference_wrapper is callable (in C++11) - // - // Concerns: - // 1. That in appropriate build modes, bsl::reference_wrapper is - // callable - // - // Plan: - // 1. Verify `BSLSTL_REFRENCEWRAPPER_IS_ALIASED` is `true` on - // on C++14 platforms. Note that this test is a sanity check - // and deliberately does not reproduce the logic in the component. - // - // 2. Verify if `BSLSTL_REFRENCEWRAPPER_IS_ALIASED` is `true` - // `bsl::reference_wrapper` is an alias to the platform standard - // library. - // - // 3. Verify if `BSLSTL_REFRENCEWRAPPER_IS_ALIASED` we can - // assign a function reference to a `reference_wrapper` and - // invoke it. - // - // Testing: - // operator()(...) const; - // -------------------------------------------------------------------- - - if (verbose) { - printf("\nTESTING CALLABLE\n" - "\n================\n"); - } - -#if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201402L // sanity check -#ifndef BSLSTL_REFRENCEWRAPPER_IS_ALIASED - BSLMF_ASSERT(false && "reference_wrapper not aliased in C++14"); -#endif -#endif - -#ifdef BSLSTL_REFRENCEWRAPPER_IS_ALIASED - if (verbose) { - printf("\tverify `reference_wrapper` is an alias to std\n"); - } - - ASSERT(true == - (bsl::is_same, - bsl::reference_wrapper >::value)); - - if (verbose) { - printf("\tverify `reference_wrapper` is callbable\n"); - } - - { - Callable c; - bsl::reference_wrapper ref = bsl::ref(c); - ref(); - ASSERT(42 == ref(0)); - } - { - Callable c; - bsl::reference_wrapper ref = bsl::cref(c); - ASSERT(-42 == ref(0)); - } -#endif // BSLSTL_REFRENCEWRAPPER_IS_ALIASED - - } break; - case 2: { - // -------------------------------------------------------------------- - // TYPE TRAITS - // - // Concerns: - // 1. `bslmf::IsBitwiseMoveable>::value` is - // true regardless of the type of `T`. - // - // 2. `bslmf::IsReferenceWrapper>::value` is - // true regardless of the type of `T`. - // - // Plan: - // 1. For concern 1, instantiate `reference_wrapper` with both bitwise - // moveable and non-bitwise moveable types and verify that the - // `bslmf::isBitwiseMovable` trait is true for both cases. - // - // 2. For concern 2, instantiate `reference_wrapper` with 2 - // unrelated types and verify that the `bslmf::IsReferenceWrapper` - // trait is true for both cases. - // - // Testing: - // TYPE TRAITS - // -------------------------------------------------------------------- - - if (verbose) printf("\nTYPE TRAITS" - "\n===========\n"); - - using BloombergLP::bslmf::IsBitwiseMoveable; - using BloombergLP::bslmf::IsReferenceWrapper; - using bsl::reference_wrapper; - - // First, verify that we have one bitwise movable type and one not - // bitwise moveable type. - ASSERT( IsBitwiseMoveable::value); - ASSERT(! IsBitwiseMoveable::value); - - // Now test that `reference_wrapper` is bitwise moveable in either - // case. - ASSERT(IsBitwiseMoveable >::value); - ASSERT(IsBitwiseMoveable >::value); - - // Test that `reference_wrapper` is indeed a reference wrapper. - ASSERT( IsReferenceWrapper >::value); - ASSERT( IsReferenceWrapper >::value); - - // Test that the trait specialization provided by this component does - // not incidentally cause `IsReferenceWrapper` to be true for actual - // reference types. - ASSERT(! IsReferenceWrapper::value); - ASSERT(! IsReferenceWrapper::value); - - } break; case 1: { // -------------------------------------------------------------------- - // BASIC TESTS - // Create objects each possible way, verify they have the right - // contents and can be used in the standard ways. + // VERIFY EXISTENCE OF NAMES // // Concerns: - // 1. Template functions defined are only checked by the compiler when - // called, so all templates must be instantiated here. - // - // 2. The various functions' argument must be copied into the object - // correctly. - // - // 3. The accessors must reproduce the various functions' argument - // values. + // 1. `` was included // // Plan: - // 1. Define a dummy type. + // 1. Define a dummy `typedef` using `bsl::reference_wrapper`. // - // 2. Wrap the dummy type using each available method. + // 2. Get the address of the free functions. // // 3. Use the wrappers' explicit and implicit accessors. (C-1..3) // // Testing: - // reference_wrapper(T&); - // reference_wrapper(const reference_wrapper&); - // reference_wrapper& operator=(reference_wrapper&); - // operator T&() const; - // T& get() const; + // reference_wrapper; // reference_wrapper cref(const T&); // reference_wrapper cref(reference_wrapper); // reference_wrapper ref(T&); // reference_wrapper ref(reference_wrapper); // -------------------------------------------------------------------- - if (verbose) { - printf("\nBASIC TESTS" - "\n===========\n"); - } - - Dummy a; - const Dummy b = {}; - - ASSERT(!isConst(a) && isConst(b)); // Test `isConst`. + if (verbose) puts("\nVERIFY EXISTENCE OF NAMES" + "\n========================="); - bsl::reference_wrapper< Dummy> rwa (a); - bsl::reference_wrapper rwca(a); - bsl::reference_wrapper rwcb(b); + int i = 42; + bsl::reference_wrapper irw(i); - bsl::reference_wrapper< Dummy> copyrwa (rwa ); - bsl::reference_wrapper copyrwca(rwca); - bsl::reference_wrapper copyrwcb(rwcb); + bsl::reference_wrapper irw2 = bsl::ref(i); + ASSERT(&irw.operator int& () == &irw2.operator int& ()); + bsl::reference_wrapper irw3 = bsl::ref(irw2); + ASSERT(&irw2.operator int& () == &irw3.operator int& ()); - ASSERT(!isConst(rwa)); // Check conversion to ref type, constness. - ASSERT( isConst(rwca)); // Likewise. - ASSERT( isConst(rwcb)); + bsl::reference_wrapper cirw = bsl::cref(i); + ASSERT(&irw.operator int& () == &cirw.operator const int& ()); + bsl::reference_wrapper cirw2 = bsl::cref(cirw); + ASSERT(&cirw.operator const int& () == &cirw2.operator const int& ()); - copyrwa = a; // Assign from raw reference. - copyrwca = a; // Likewise. - copyrwcb = b; - - copyrwa = rwa; // Assign from other `reference_wrapper`. - copyrwca = rwca; // Likewise. - copyrwcb = rwcb; - - Dummy& rax = rwa; // Initialize from `reference_wrapper`. - const Dummy& rcax = rwca; // Likewise. - const Dummy& rcbx = rwcb; - - Dummy& ray = bsl::ref(a); // Initialize from ref result. - const Dummy& rcay = bsl::cref(a); // Likewise. - const Dummy& rcby = bsl::cref(b); - - ASSERT(!isConst(bsl::ref (a))); - ASSERT( isConst(bsl::cref(a))); - ASSERT( isConst(bsl::cref(b))); - - ASSERT(!isConst(bsl::ref (rwa ))); - ASSERT( isConst(bsl::cref(rwca))); - ASSERT( isConst(bsl::cref(rwcb))); - - bsl::reference_wrapper< Dummy> copyrwaz (bsl::ref(rwa )); - bsl::reference_wrapper copyrwcaz(bsl::ref(rwca)); - bsl::reference_wrapper copyrwcbz(bsl::ref(rwcb)); - - bsl::reference_wrapper copyrwcazb(bsl::cref(rwca)); - bsl::reference_wrapper copyrwcbzc(bsl::cref(rwcb)); - - Dummy c; - - bsl::reference_wrapper assrwaz(bsl::ref(rwa)); - assrwaz = a; - assrwaz = c; - assrwaz = rwa; - - bsl::reference_wrapper assrwcaz(bsl::ref(rwca)); - assrwcaz = b; - assrwcaz = c; - assrwcaz = rwca; - assrwcaz = rwcb; + const bool BSLSTL_REFRENCEWRAPPER_IS_ALIASED_is_defined = +#ifdef BSLSTL_REFRENCEWRAPPER_IS_ALIASED + true; +#else + false; +#endif - ASSERT(copyrwa.get().localAddressOf() == a.localAddressOf()); - ASSERT(copyrwca.get().localAddressOf() == a.localAddressOf()); - ASSERT(copyrwcb.get().localAddressOf() == b.localAddressOf()); - ASSERT(copyrwaz.get().localAddressOf() == a.localAddressOf()); - ASSERT(copyrwcaz.get().localAddressOf() == a.localAddressOf()); - ASSERT(copyrwcbz.get().localAddressOf() == b.localAddressOf()); + const bool BSLMF_REFERENCEWRAPPER_IS_ALIASED_is_defined = +#ifdef BSLMF_REFERENCEWRAPPER_IS_ALIASED + true; +#else + false; +#endif - // These do not test much, but they seem preferable to "void(e)": + ASSERT(BSLMF_REFERENCEWRAPPER_IS_ALIASED_is_defined == + BSLSTL_REFRENCEWRAPPER_IS_ALIASED_is_defined); - ASSERT(rax.localAddressOf() == a.localAddressOf()); - ASSERT(rcax.localAddressOf() == a.localAddressOf()); - ASSERT(rcbx.localAddressOf() == b.localAddressOf()); - ASSERT(ray.localAddressOf() == a.localAddressOf()); - ASSERT(rcay.localAddressOf() == a.localAddressOf()); - ASSERT(rcby.localAddressOf() == b.localAddressOf()); - ASSERT(copyrwcazb.get().localAddressOf() == a.localAddressOf()); - ASSERT(copyrwcbzc.get().localAddressOf() == b.localAddressOf()); } break; default: { fprintf(stderr, "WARNING: CASE `%d' NOT FOUND.\n", test); @@ -495,7 +150,7 @@ int main(int argc, char *argv[]) } // ---------------------------------------------------------------------------- -// Copyright 2013 Bloomberg Finance L.P. +// Copyright 2024 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From fa9bea49af875ef4125e74207d32a646c5884fcc Mon Sep 17 00:00:00 2001 From: afeher Date: Thu, 7 Nov 2024 11:08:49 -0500 Subject: [PATCH 02/11] Bug fix --- groups/bsl/bslmf/bslmf_unwrapreference.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.h b/groups/bsl/bslmf/bslmf_unwrapreference.h index f473a825cf..101e87b2b8 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.h +++ b/groups/bsl/bslmf/bslmf_unwrapreference.h @@ -89,13 +89,13 @@ struct unwrap_reference { typedef t_TYPE type; }; -/// This partial specialization of `bsl::remove_reference`, for when the +/// This partial specialization of `bsl::unwrap_reference`, for when the /// template parameter `t_TYPE` is a `bsl::reference_wrapper`, provides a /// `typedef`, `type`, that is `t_TYPE::type`. -template -struct remove_reference { +template <> +struct unwrap_reference > { - typedef t_TYPE type; + typedef t_TYPE& type; }; #if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES) From 5a12f53b5f3b53ae355ba4dcf3ba46501c21b5f6 Mon Sep 17 00:00:00 2001 From: afeher Date: Thu, 7 Nov 2024 11:54:05 -0500 Subject: [PATCH 03/11] More bug fix. --- groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 2 +- groups/bsl/bslmf/bslmf_unwrapreference.h | 6 +++--- groups/bsl/bslmf/bslmf_unwrapreference.t.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp index 4614f97bd0..c84cb2212f 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -281,7 +281,7 @@ int main(int argc, char *argv[]) ASSERT((bsl::is_same, std::unwrap_ref_decay_t >::value)); #else - if (veryVerbose) put("\tSkipped: standard types aren't available"); + if (veryVerbose) puts("\tSkipped: standard types aren't available"); #endif } break; case 1: { diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.h b/groups/bsl/bslmf/bslmf_unwrapreference.h index 101e87b2b8..792edcc247 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.h +++ b/groups/bsl/bslmf/bslmf_unwrapreference.h @@ -92,10 +92,10 @@ struct unwrap_reference { /// This partial specialization of `bsl::unwrap_reference`, for when the /// template parameter `t_TYPE` is a `bsl::reference_wrapper`, provides a /// `typedef`, `type`, that is `t_TYPE::type`. -template <> -struct unwrap_reference > { +template +struct unwrap_reference > { - typedef t_TYPE& type; + typedef t_WRAPPED_TYPE& type; }; #if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES) diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp index b3efae68b2..f944eda636 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp @@ -203,7 +203,7 @@ int main(int argc, char *argv[]) ASSERT((bsl::is_same, std::unwrap_reference_t >::value)); #else - if (veryVerbose) put("\tSkipped: standard types aren't available"); + if (veryVerbose) puts("\tSkipped: standard types aren't available"); #endif } break; case 1: { From e91812b2fe1c917953b2cd9c74271ec6f4bd741d Mon Sep 17 00:00:00 2001 From: afeher Date: Thu, 7 Nov 2024 11:56:35 -0500 Subject: [PATCH 04/11] Comment clean up --- groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 2 -- groups/bsl/bslmf/bslmf_unwrapreference.t.cpp | 2 -- 2 files changed, 4 deletions(-) diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp index c84cb2212f..4a17b54626 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -317,8 +317,6 @@ int main(int argc, char *argv[]) if (verbose) puts("\nTESTING `bsl::unwrap_ref_decay::type`" "\n====================================="); - // C-1 - #define ASSERT_UNWRAP_REF_(TYPE, RESULT) \ ASSERT((true == bsl::is_same::type, \ RESULT>::value)) diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp index f944eda636..3d79341133 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp @@ -238,8 +238,6 @@ int main(int argc, char *argv[]) if (verbose) puts("\nTESTING `bsl::unwrap_reference::type`" "\n====================================="); - // C-1 - #define ASSERT_UNWRAP_REF_(TYPE, RESULT) \ ASSERT((true == bsl::is_same::type, \ RESULT>::value)) From cb40cb0fddf288b02b24886461f41f858f6f4890 Mon Sep 17 00:00:00 2001 From: afeher Date: Thu, 7 Nov 2024 12:49:06 -0500 Subject: [PATCH 05/11] Add inclusion to canonical headers. --- groups/bsl/bsl+bslhdrs/bsl_functional.h | 2 ++ groups/bsl/bsl+bslhdrs/bsl_type_traits.h | 2 ++ groups/bsl/bslmf/bslmf_unwraprefdecay.h | 2 ++ groups/bsl/bslmf/bslmf_unwrapreference.h | 2 ++ 4 files changed, 8 insertions(+) diff --git a/groups/bsl/bsl+bslhdrs/bsl_functional.h b/groups/bsl/bsl+bslhdrs/bsl_functional.h index 4312fddb34..f71478a094 100644 --- a/groups/bsl/bsl+bslhdrs/bsl_functional.h +++ b/groups/bsl/bsl+bslhdrs/bsl_functional.h @@ -130,6 +130,8 @@ namespace bsl { #include #include #include +#include +#include #endif // INCLUDED_BSL_FUNCTIONAL diff --git a/groups/bsl/bsl+bslhdrs/bsl_type_traits.h b/groups/bsl/bsl+bslhdrs/bsl_type_traits.h index 59c3c526ca..e287301d7d 100644 --- a/groups/bsl/bsl+bslhdrs/bsl_type_traits.h +++ b/groups/bsl/bsl+bslhdrs/bsl_type_traits.h @@ -656,6 +656,8 @@ using std::void_t; #include #include #include +#include +#include #include #endif diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.h b/groups/bsl/bslmf/bslmf_unwraprefdecay.h index c8be165d3b..29fd4bfcac 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.h +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.h @@ -11,6 +11,8 @@ BSLS_IDENT("$Id: $") // bsl::unwrap_ref_decay: standard meta-function to unwrap decayed ref wrapper // bsl::unwrap_ref_decay_t: alias to the return type of the meta-function // +//@CANONICAL_HEADER: bsl_functional.h, bsl_type_traits.h +// //@SEE_ALSO: bslmf_addreference // //@DESCRIPTION: This component defines a meta-function `bsl::unwrap_ref_decay` diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.h b/groups/bsl/bslmf/bslmf_unwrapreference.h index 792edcc247..8efe13b7c5 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.h +++ b/groups/bsl/bslmf/bslmf_unwrapreference.h @@ -11,6 +11,8 @@ BSLS_IDENT("$Id: $") // bsl::unwrap_reference: standard meta-function to unwrap reference wrappers // bsl::unwrap_reference_t: alias to the return type of the meta-function // +//@CANONICAL_HEADER: bsl_functional.h, bsl_type_traits.h +// //@SEE_ALSO: bslmf_addreference // //@DESCRIPTION: This component defines a meta-function `bsl::unwrap_reference` From 568b5d296e08644936eb431c58ace003149ac137 Mon Sep 17 00:00:00 2001 From: afeher Date: Thu, 7 Nov 2024 12:58:26 -0500 Subject: [PATCH 06/11] Bug fix --- groups/bsl/bslmf/bslmf_unwraprefdecay.h | 15 +++++++++++++-- groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 7 +++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.h b/groups/bsl/bslmf/bslmf_unwraprefdecay.h index 29fd4bfcac..b75cb5e9b1 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.h +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.h @@ -99,6 +99,13 @@ BSLS_IDENT("$Id: $") // int *&>::value)); // // // Not wrapped types decay +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType *>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedTypePointer>::value)); +// // assert((true == bsl::is_same::type, // NotWrappedType>::value)); // assert((true == bsl::is_same< @@ -128,7 +135,9 @@ BSLS_IDENT("$Id: $") #include +#include #include +#include #include #include @@ -157,8 +166,10 @@ using std::unwrap_ref_decay_t; template struct unwrap_ref_decay { - /// This `typedef` is an alias to the template parameter `t_TYPE`. - typedef t_TYPE type; + /// This `typedef` is an alias to the reference-unwrapped type of the + /// decayed `t_TYPE` template parameter. + typedef typename bsl::unwrap_reference< + typename bsl::decay::type >::type type; }; #ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp index 4a17b54626..3136f5ac79 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -215,6 +215,13 @@ int main(int argc, char *argv[]) WrappedTypePointer>::value)); // Not wrapped types decay + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedType *>::value)); + ASSERT((true == bsl::is_same< + bsl::unwrap_ref_decay::type, + NotWrappedTypePointer>::value)); + ASSERT((true == bsl::is_same::type, NotWrappedType>::value)); ASSERT((true == bsl::is_same< From 61604f022ddaaa3ae9511a5e8c09787f0bca4759 Mon Sep 17 00:00:00 2001 From: afeher Date: Thu, 7 Nov 2024 12:59:27 -0500 Subject: [PATCH 07/11] Cleanup --- groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp index 3136f5ac79..0674875769 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -116,7 +116,6 @@ int main(int argc, char *argv[]) printf("TEST " __FILE__ " CASE %d\n", test); - for(test=1;testStatus!=-1&&printf("TESTING: %d\n", test);++test) switch (test) { case 0: case 3: { // -------------------------------------------------------------------- From c02744a51338d8aaab6a9761780149d933f7bd72 Mon Sep 17 00:00:00 2001 From: afeher Date: Thu, 7 Nov 2024 13:58:54 -0500 Subject: [PATCH 08/11] Silence useless Sun warning --- groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 4 ++++ groups/bsl/bslmf/bslmf_unwrapreference.t.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp index 0674875769..973aed88b6 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -16,6 +16,10 @@ using namespace BloombergLP; +#if defined(BSLS_PLATFORM_CMP_SUN) + #pragma error_messages(off, reftoref) +#endif + //============================================================================= // TEST PLAN //----------------------------------------------------------------------------- diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp index 3d79341133..8d2b348ca7 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp @@ -16,6 +16,10 @@ using namespace BloombergLP; +#if defined(BSLS_PLATFORM_CMP_SUN) + #pragma error_messages(off, reftoref) +#endif + //============================================================================= // TEST PLAN //----------------------------------------------------------------------------- From 31670e6dc3b054fb556a0cc2b63dd7fc49b1049f Mon Sep 17 00:00:00 2001 From: afeher Date: Mon, 11 Nov 2024 14:04:41 -0500 Subject: [PATCH 09/11] Brian review. --- groups/bsl/bsl+bslhdrs/bsl_type_traits.h | 1 + groups/bsl/bslmf/bslmf_referencewrapper.t.cpp | 4 +- groups/bsl/bslmf/bslmf_unwraprefdecay.h | 188 +++++++++--------- groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 50 ++--- groups/bsl/bslmf/bslmf_unwrapreference.h | 50 ++--- groups/bsl/bslmf/bslmf_unwrapreference.t.cpp | 24 ++- .../bsl/bslstl/bslstl_referencewrapper.t.cpp | 10 +- 7 files changed, 174 insertions(+), 153 deletions(-) diff --git a/groups/bsl/bsl+bslhdrs/bsl_type_traits.h b/groups/bsl/bsl+bslhdrs/bsl_type_traits.h index e287301d7d..479628af3a 100644 --- a/groups/bsl/bsl+bslhdrs/bsl_type_traits.h +++ b/groups/bsl/bsl+bslhdrs/bsl_type_traits.h @@ -651,6 +651,7 @@ using std::void_t; #include #include #include +#include #include #include #include diff --git a/groups/bsl/bslmf/bslmf_referencewrapper.t.cpp b/groups/bsl/bslmf/bslmf_referencewrapper.t.cpp index 9780c99fde..2c07d74d7c 100644 --- a/groups/bsl/bslmf/bslmf_referencewrapper.t.cpp +++ b/groups/bsl/bslmf/bslmf_referencewrapper.t.cpp @@ -277,8 +277,8 @@ int main(int argc, char *argv[]) #if BSLS_COMPILERFEATURES_CPLUSPLUS >= 201402L #ifndef BSLMF_REFERENCEWRAPPER_IS_ALIASED BSLMF_ASSERT(false && "reference_wrapper not aliased in C++14"); -#endif // BSLMF_REFERENCEWRAPPER_IS_ALIASED -#endif // At least C++14 +#endif +#endif #ifdef BSLMF_REFERENCEWRAPPER_IS_ALIASED if (verbose) puts("\tverify `reference_wrapper` is an alias to std"); diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.h b/groups/bsl/bslmf/bslmf_unwraprefdecay.h index b75cb5e9b1..e4e4164985 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.h +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.h @@ -13,13 +13,14 @@ BSLS_IDENT("$Id: $") // //@CANONICAL_HEADER: bsl_functional.h, bsl_type_traits.h // -//@SEE_ALSO: bslmf_addreference +//@SEE_ALSO: bslmf_referencewrapper, bslmf_uwrap_reference // //@DESCRIPTION: This component defines a meta-function `bsl::unwrap_ref_decay` -// that may be used to unwrap a decayed (`bsl::decay`) `bsl::reference_wrapper` -// or a `std::reference_wrapper` of some type `U`, resulting in `U&`. In case -// the specified type template argument is not an specialization of either -// `reference_wrapper` (after decaying) the result is the type itself. +// that may be used to unwrap a possibly cv-qualified `bsl::reference_wrapper` +// (which is an alias of `std::reference_wrapper` if that exists) +// specialization or reference thereto of some type `U`, resulting in `U&`. In +// case the specified type template argument is not a specialization of +// `bsl::reference_wrapper` the result is the type, but decayed (`bsl::decay`). // // `bsl::unwrap_ref_decay` meets the requirements of the `unwrap_ref_decay` // template defined in the C++20 standard [meta.trans.other]. @@ -31,103 +32,106 @@ BSLS_IDENT("$Id: $") ///Example 1: Unwrap Reference Wrapped Argument Types /// - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose that we work in a programming environment where function argument -// types may be presented as is, or wrapped in a `bsl::reference_wrapper` or -// its `std` equivalent and we would like to create a member or local variable -// while obeying the request for reference-wrapping. So when the argument type -// decays into a reference wrapper we would like to use a reference to the -// wrapped type, and simply use the decayed variations of the unwrapped types. -// This is a use case for `bsl::unwrap_ref_decay`. +// types may be presented as is, or wrapped in a `bsl::reference_wrapper` and +// we would like to create a member or local variable while obeying the request +// for the reference-wrapper represents. As arguments may come potentially +// cv-qualified, as well as references we need to first decay them to remove +// cv-qualification, reference and/or turn arrays into a pointer etc. (see +// `bsl::decay`). When the argument type decays into a reference wrapper we +// want to use a reference to the wrapped type, and simply use the decayed +// variations of the unwrapped types. This is a use case for +// `bsl::unwrap_ref_decay`. // // First, we create types that may be the bases for reference-wrapped, and // normal type parameters: // ``` -// typedef bsl::reference_wrapper WrappedType; -// typedef int *NotWrappedType; +// typedef bsl::reference_wrapper WrappedType; +// typedef int *NotWrappedType; // ``` // Next, we create types that represent possible function argument types: // ``` -// typedef WrappedType WrappedTypeArray[5]; -// typedef WrappedType *WrappedTypePointer; -// typedef const WrappedType ConstWrappedType; -// typedef volatile WrappedType VolatileWrappedType; -// typedef const volatile WrappedType CvWrappedType; -// typedef WrappedType& WrappedTypeRef; -// typedef const WrappedType& ConstWrappedTypeRef; -// typedef volatile WrappedType& VolatileWrappedTypeRef; -// typedef const volatile WrappedType& CvWrappedTypeRef; +// typedef WrappedType WrappedTypeArray[5]; +// typedef WrappedType *WrappedTypePointer; +// typedef const WrappedType ConstWrappedType; +// typedef volatile WrappedType VolatileWrappedType; +// typedef const volatile WrappedType CvWrappedType; +// typedef WrappedType& WrappedTypeRef; +// typedef const WrappedType& ConstWrappedTypeRef; +// typedef volatile WrappedType& VolatileWrappedTypeRef; +// typedef const volatile WrappedType& CvWrappedTypeRef; // -// typedef NotWrappedType NotWrappedTypeArray[5]; -// typedef NotWrappedType *NotWrappedTypePointer; -// typedef const NotWrappedType ConstNotWrappedType; -// typedef volatile NotWrappedType VolatileNotWrappedType; -// typedef const volatile NotWrappedType CvNotWrappedType; -// typedef NotWrappedType& NotWrappedTypeRef; -// typedef const NotWrappedType& ConstNotWrappedTypeRef; -// typedef volatile NotWrappedType& VolatileNotWrappedTypeRef; -// typedef const volatile NotWrappedType& CvNotWrappedTypeRef; +// typedef NotWrappedType NotWrappedTypeArray[5]; +// typedef NotWrappedType *NotWrappedTypePointer; +// typedef const NotWrappedType ConstNotWrappedType; +// typedef volatile NotWrappedType VolatileNotWrappedType; +// typedef const volatile NotWrappedType CvNotWrappedType; +// typedef NotWrappedType& NotWrappedTypeRef; +// typedef const NotWrappedType& ConstNotWrappedTypeRef; +// typedef volatile NotWrappedType& VolatileNotWrappedTypeRef; +// typedef const volatile NotWrappedType& CvNotWrappedTypeRef; // ``` // Finally we can verify and demonstrate how all these types turn into a // decayed type, and only those that decay into a reference-wrapper type will // become themselves references. Notice that an array of reference wrappers // decays into a pointer to a wrapper, so it will not turn into a reference. // ``` -// assert((true == bsl::is_same::type, -// WrappedType *>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// WrappedTypePointer>::value)); +// assert((true == bsl::is_same::type, +// WrappedType *>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// WrappedTypePointer>::value)); // -// assert((true == bsl::is_same::type, -// int *&>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// int *&>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// int *&>::value)); -// assert((true == bsl::is_same::type, -// int *&>::value)); -// assert((true == bsl::is_same::type, -// int *&>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// int *&>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// int *&>::value)); -// assert((true == bsl::is_same::type, -// int *&>::value)); +// assert((true == bsl::is_same::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same::type, +// int *&>::value)); +// assert((true == bsl::is_same::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// int *&>::value)); +// assert((true == bsl::is_same::type, +// int *&>::value)); // -// // Not wrapped types decay -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedType *>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedTypePointer>::value)); +// // Not wrapped types decay +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType *>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedTypePointer>::value)); // -// assert((true == bsl::is_same::type, -// NotWrappedType>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedType>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedType>::value)); -// assert((true == bsl::is_same::type, -// NotWrappedType>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedType>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedType>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedType>::value)); -// assert((true == bsl::is_same< -// bsl::unwrap_ref_decay::type, -// NotWrappedType>::value)); +// assert((true == bsl::is_same::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); +// assert((true == bsl::is_same< +// bsl::unwrap_ref_decay::type, +// NotWrappedType>::value)); // ``` // Note, that (when available) the `bsl::unwrap_ref_decay_t` avoids the // `::type` suffix and `typename` prefix when we want to use the result of the @@ -161,24 +165,24 @@ using std::unwrap_ref_decay_t; /// defined in the C++20 standard [meta.trans.other], providing an alias, /// `type`, that returns the result. `type` has the same type as the /// (template parameter) `t_TYPE` unless `bsl::decay::type` is a -/// specialization of `bsl::reference_wrapper` or `std::reference_wrapper` -/// for a type U, in which case `type` shall be `U&`. +/// specialization of `bsl::reference_wrapper` (which is an alias to +/// `std::reference_wrapper` when that exists) for a type `U`, in which case +/// `type` shall be `U&`. template struct unwrap_ref_decay { + // TYPES /// This `typedef` is an alias to the reference-unwrapped type of the /// decayed `t_TYPE` template parameter. typedef typename bsl::unwrap_reference< - typename bsl::decay::type >::type type; + typename bsl::decay::type>::type type; }; #ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES +/// 'unwrap_ref_decay_t' is an alias to the return type of the +/// 'bsl::unwrap_ref_decay' meta-function. template using unwrap_ref_decay_t = typename unwrap_ref_decay::type; - // 'unwrap_ref_decay_t' is an alias to the return type of the - // 'bsl::unwrap_ref_decay' meta-function. Note, that the - // 'unwrap_ref_decay_t' avoids the '::type' suffix and 'typename' prefix - // when we want to use the result of the meta-function in templates. #endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES #endif // else of BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp index 973aed88b6..1748616b79 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -1,7 +1,7 @@ // bslmf_unwraprefdecay.t.cpp -*-C++-*- #include -#include // for testing only +#include #include #include @@ -25,26 +25,26 @@ using namespace BloombergLP; //----------------------------------------------------------------------------- // Overview // -------- -// The component under test defines a meta-function `bsl::unwrap_reference` -// that unwraps a reference wrapper specialization `bsl::reference_wrapper` -// or `std::reference_wrapper` template `TYPE` argument by providing a -// `type` member with the type `U&`. If the specified `TYPE` is not a -// specialization of either reference wrapper the member `type` shall be -// `TYPE`. +// The component under test defines a meta-function `bsl::unwrap_ref_decay` +// that decays its template `TYPE` argument then it unwraps it if it is a +// reference wrapper specialization `bsl::reference_wrapper` (which is an +// alias to `std::reference_wrapper` when that exists) by providing a `type` +// member with the type `U&`. If the specified `TYPE` does not decay into a +// specialization of either reference wrapper the member `type` shall be the +// decayed `TYPE`. // // The component also defines an alias to the result type of the -// `bsl::unwrap_reference` meta-function. Thus, we need to ensure that the +// `bsl::unwrap_ref_decay` meta-function. Thus, we need to ensure that the // value returned by the meta-function is correct for each possible category of // types. // -// `bsl::unwrap_reference` and `bsl::unwrap_reference_t` should be aliased to -// `std::unwrap_reference` and `std::unwrap_reference_t`, respectively when the +// `bsl::unwrap_ref_decay` and `bsl::unwrap_ref_decay_t` should be aliased to +// `std::unwrap_ref_decay` and `std::unwrap_ref_decay_t`, respectively when the // standard meta functions are available from the native library. // // ---------------------------------------------------------------------------- -// PUBLIC TYPES -// [ 1] bsl::unwrap_reference::type -// [ 1] bsl::unwrap_reference_t +// [ 1] bsl::unwrap_ref_decay::type +// [ 1] bsl::unwrap_ref_decay_t // // ---------------------------------------------------------------------------- // [ 3] USAGE EXAMPLE @@ -144,12 +144,15 @@ int main(int argc, char *argv[]) ///Example 1: Unwrap Reference Wrapped Argument Types /// - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose that we work in a programming environment where function argument -// types may be presented as is, or wrapped in a `bsl::reference_wrapper` or -// its `std` equivalent and we would like to create a member or local variable -// while obeying the request for reference-wrapping. So when the argument type -// decays into a reference wrapper we would like to use a reference to the -// wrapped type, and simply use the decayed variations of the unwrapped types. -// This is a use case for `bsl::unwrap_ref_decay`. +// types may be presented as is, or wrapped in a `bsl::reference_wrapper` and +// we would like to create a member or local variable while obeying the request +// for the reference-wrapper represents. As arguments may come potentially +// cv-qualified, as well as references we need to first decay them to remove +// cv-qualification, reference and/or turn arrays into a pointer etc. (see +// `bsl::decay`). When the argument type decays into a reference wrapper we +// want to use a reference to the wrapped type, and simply use the decayed +// variations of the unwrapped types. This is a use case for +// `bsl::unwrap_ref_decay`. // // First, we create types that may be the bases for reference-wrapped, and // normal type parameters: @@ -260,16 +263,16 @@ int main(int argc, char *argv[]) // Concerns: // 1. The meta functions `bsl::unwrap_ref_decay` and // `bsl::unwrap_ref_decay_t` should be aliased to their standard - // library analogs when the latter is available from the native + // library analogs when the latter are available from the native // library. // // Plan: // 1. If `BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY` is defined // 1. Use `bsl::is_same` to compare `bsl::remove_ref_decay` to - // `std::remove_ref_decay` using a representative type. + // `std::remove_ref_decay` using a representative type. (C-1) // // 2. Use `bsl::is_same` to compare `bsl::remove_reference_t` to - // `std::remove_reference_t` using a representative type. + // `std::remove_reference_t` using a representative type. (C-1) // // Testing: // CONCERN: Aliased to standard types when available. @@ -406,8 +409,7 @@ int main(int argc, char *argv[]) ASSERT_UNWRAP_REF_WRAPPED(void*, void*&); ASSERT_UNWRAP_REF_WRAPPED(int, int&); - ASSERT_UNWRAP_REF_WRAPPED(int&, int&); - ASSERT_UNWRAP_REF_WRAPPED(const int&, const int&); + ASSERT_UNWRAP_REF_WRAPPED(const int, const int&); ASSERT_UNWRAP_REF_WRAPPED(const volatile int, const volatile int&); ASSERT_UNWRAP_REF_WRAPPED(Enum, Enum&); ASSERT_UNWRAP_REF_WRAPPED(Struct, Struct&); diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.h b/groups/bsl/bslmf/bslmf_unwrapreference.h index 8efe13b7c5..3a2f2b158e 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.h +++ b/groups/bsl/bslmf/bslmf_unwrapreference.h @@ -13,13 +13,13 @@ BSLS_IDENT("$Id: $") // //@CANONICAL_HEADER: bsl_functional.h, bsl_type_traits.h // -//@SEE_ALSO: bslmf_addreference +//@SEE_ALSO: bslmf_referencewrapper, bslmf_uwrap_ref_decay // //@DESCRIPTION: This component defines a meta-function `bsl::unwrap_reference` -// that may be used to unwrap a `bsl::reference_wrapper` or a -// `std::reference_wrapper` of some type `U`, resulting in `U&`. In case the -// specified type template argument is not an specialization of either -// `reference_wrapper` the result is the type itself. +// that may be used to unwrap a `bsl::reference_wrapper` (which is an alias of +// `std::reference_wrapper` when that exists) of some type `U`, resulting in +// `U&`. In case the specified type template argument is not an specialization +// of `bsl::reference_wrapper` the result is the type itself. // // `bsl::unwrap_reference` meets the requirements of the `unwrap_reference` // template defined in the C++20 standard [meta.trans.other]. @@ -38,19 +38,19 @@ BSLS_IDENT("$Id: $") // First, we create types that represent both reference-wrapped, and normal // type parameters: // ``` -// typedef bsl::reference_wrapper WrappedType; -// typedef int *NotWrappedType; +// typedef bsl::reference_wrapper WrappedType; +// typedef int *NotWrappedType; // ``` // Next, we create types that are references if they were wrapped: // ``` -// typedef bsl::unwrap_reference::type UnwrappedWrapped; -// typedef bsl::unwrap_reference::type UnwrappedNotWrapped; +// typedef bsl::unwrap_reference::type UnwrappedWrapped; +// typedef bsl::unwrap_reference::type UnwrappedNotWrapped; // ``` // Finally we can verify that the wrapped type became a reference, while the // other type is unchanged: // ``` -// assert((true == bsl::is_same::value)); -// assert((true == bsl::is_same::value)); +// assert((true == bsl::is_same::value)); +// assert((true == bsl::is_same::value)); // ``` // Note, that (when available) the `bsl::unwrap_reference_t` avoids the // `::type` suffix and `typename` prefix when we want to use the result of the @@ -64,7 +64,7 @@ BSLS_IDENT("$Id: $") #include #if BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY - #include // 'std::unwrap_reference', 'std::unwrap_reference_t' + #include // 'std::unwrap_reference', 'std::unwrap_reference_t' #endif // ====================== @@ -80,37 +80,39 @@ using std::unwrap_reference_t; /// This `struct` template implements the `unwrap_reference` meta-function /// defined in the C++20 standard [meta.trans.other], providing an alias, -/// `type`, that returns the result. `type` has the same type as the +/// `type`, that returns the result. `type` denotes the same type as the /// (template parameter) `t_TYPE` unless `t_TYPE` is a specialization of -/// `bsl::reference_wrapper` or `std::reference_wrapper` for a type U, in -/// which case `type` shall be `U&`. +/// `bsl::reference_wrapper` (which is an alias of `std::reference_wrapper` +/// if that exists) for a type `U`, in which case `type` is `U&`. template struct unwrap_reference { + // TYPES /// This `typedef` is an alias to the template parameter `t_TYPE`. typedef t_TYPE type; }; -/// This partial specialization of `bsl::unwrap_reference`, for when the -/// template parameter `t_TYPE` is a `bsl::reference_wrapper`, provides a -/// `typedef`, `type`, that is `t_TYPE::type`. +/// This partial specialization is chosen when the template parameter `t_TYPE` +/// is a `bsl::reference_wrapper`. template struct unwrap_reference > { + // TYPES + + /// This `typedef` is an alias to the template parameter `t_WRAPPED_TYPE&`. typedef t_WRAPPED_TYPE& type; }; #if defined(BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES) // ALIASES + +/// `unwrap_reference_t` is an alias to the return type of the +/// `bsl::unwrap_reference` meta-function. template using unwrap_reference_t = typename unwrap_reference::type; - // 'unwrap_reference_t' is an alias to the return type of the - // 'bsl::unwrap_reference' meta-function. Note, that the - // 'unwrap_reference_t' avoids the '::type' suffix and 'typename' prefix - // when we want to use the result of the meta-function in templates. -#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES +#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES -#endif // else of BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY +#endif // else of BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY } // close namespace bsl diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp index 8d2b348ca7..d66ad041f8 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp @@ -1,7 +1,7 @@ // bslmf_unwrapreference.t.cpp -*-C++-*- #include -#include // for testing only +#include #include #include @@ -27,10 +27,10 @@ using namespace BloombergLP; // -------- // The component under test defines a meta-function `bsl::unwrap_reference` // that unwraps a reference wrapper specialization `bsl::reference_wrapper` -// or `std::reference_wrapper` template `TYPE` argument by providing a -// `type` member with the type `U&`. If the specified `TYPE` is not a -// specialization of either reference wrapper the member `type` shall be -// `TYPE`. +// (which is an alias to `std::reference_wrapper` when that exists) template +// `TYPE` argument by providing a `type` member with the type `U&`. If the +// specified `TYPE` is not a specialization of either reference wrapper the +// member `type` shall be `TYPE`. // // The component also defines an alias to the result type of the // `bsl::unwrap_reference` meta-function. Thus, we need to ensure that the @@ -42,7 +42,6 @@ using namespace BloombergLP; // standard meta functions are available from the native library. // // ---------------------------------------------------------------------------- -// PUBLIC TYPES // [ 1] bsl::unwrap_reference::type // [ 1] bsl::unwrap_reference_t // @@ -176,16 +175,16 @@ int main(int argc, char *argv[]) // Concerns: // 1. The meta functions `bsl::unwrap_reference` and // `bsl::unwrap_reference_t` should be aliased to their standard - // library analogs when the latter is available from the native + // library analogs when the latter are available from the native // library. // // Plan: // 1. If `BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY` is defined // 1. Use `bsl::is_same` to compare `bsl::unwrap_reference` to - // `std::unwrap_reference` using a representative type. + // `std::unwrap_reference` using a representative type. (C-1) // // 2. Use `bsl::is_same` to compare `bsl::unwrap_reference_t` to - // `std::unwrap_reference_t` using a representative type. + // `std::unwrap_reference_t` using a representative type. (C-1) // // Testing: // CONCERN: Aliased to standard types when available. @@ -266,6 +265,11 @@ int main(int argc, char *argv[]) ASSERT_UNWRAP_REF(int Class::*, int Class::*); + ASSERT_UNWRAP_REF(void(int), void(int)); + ASSERT_UNWRAP_REF(void(*)(int), void(*)(int)); + + ASSERT_UNWRAP_REF(void, void); + #ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY #define ASSERT_UNWRAP_REF_WRAPPED(TYPE, RESULT) \ ASSERT_UNWRAP_REF(bsl::reference_wrapper, RESULT); \ @@ -285,6 +289,8 @@ int main(int argc, char *argv[]) ASSERT_UNWRAP_REF_WRAPPED(int Class::*, int Class::*&); + ASSERT_UNWRAP_REF_WRAPPED(void(int), void(&)(int)); + } break; default: { fprintf(stderr, "WARNING: CASE `%d' NOT FOUND.\n", test); diff --git a/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp b/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp index e99d9f9581..f57f6321e1 100644 --- a/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp +++ b/groups/bsl/bslstl/bslstl_referencewrapper.t.cpp @@ -12,7 +12,7 @@ // Overview // -------- // The component under test is a legacy, backwards compatibility component that -// simply `#include`s ``. In this test driver we +// simply `#include`s ``. In this test driver we // simply verify that the names in `bsl` exist, and that the // `BSLSTL_REFRENCEWRAPPER_IS_ALIASED` macro is defined when expected. // @@ -93,7 +93,11 @@ int main(int argc, char *argv[]) // // 2. Get the address of the free functions. // - // 3. Use the wrappers' explicit and implicit accessors. (C-1..3) + // 3. Use the wrappers' explicit and implicit accessors. (C-1) + // + // 4. Verify that `BSLSTL_REFRENCEWRAPPER_IS_ALIASED` is defined when + // `BSLLMF_REFRENCEWRAPPER_IS_ALIASED` is defined, and othwerwise + // it is not defined. // // Testing: // reference_wrapper; @@ -101,6 +105,7 @@ int main(int argc, char *argv[]) // reference_wrapper cref(reference_wrapper); // reference_wrapper ref(T&); // reference_wrapper ref(reference_wrapper); + // BSLSTL_REFRENCEWRAPPER_IS_ALIASED // -------------------------------------------------------------------- if (verbose) puts("\nVERIFY EXISTENCE OF NAMES" @@ -108,6 +113,7 @@ int main(int argc, char *argv[]) int i = 42; bsl::reference_wrapper irw(i); + ASSERT(&irw.operator int& () == &i); bsl::reference_wrapper irw2 = bsl::ref(i); ASSERT(&irw.operator int& () == &irw2.operator int& ()); From 6c319fb4f343ad53514bc2a0137fdf541ecd915d Mon Sep 17 00:00:00 2001 From: afeher Date: Tue, 10 Dec 2024 11:44:46 -0500 Subject: [PATCH 10/11] Brian review #2. --- groups/bsl/bslmf/bslmf_unwraprefdecay.h | 32 +++++++++---------- groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp | 27 +++++----------- groups/bsl/bslmf/bslmf_unwrapreference.h | 11 +++---- groups/bsl/bslmf/bslmf_unwrapreference.t.cpp | 12 ++++--- .../bsl/bslstl/bslstl_referencewrapper.t.cpp | 4 +-- 5 files changed, 37 insertions(+), 49 deletions(-) diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.h b/groups/bsl/bslmf/bslmf_unwraprefdecay.h index e4e4164985..341fa96595 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.h +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.h @@ -13,7 +13,7 @@ BSLS_IDENT("$Id: $") // //@CANONICAL_HEADER: bsl_functional.h, bsl_type_traits.h // -//@SEE_ALSO: bslmf_referencewrapper, bslmf_uwrap_reference +//@SEE_ALSO: bslmf_referencewrapper, bslmf_unwrap_reference // //@DESCRIPTION: This component defines a meta-function `bsl::unwrap_ref_decay` // that may be used to unwrap a possibly cv-qualified `bsl::reference_wrapper` @@ -34,12 +34,11 @@ BSLS_IDENT("$Id: $") // Suppose that we work in a programming environment where function argument // types may be presented as is, or wrapped in a `bsl::reference_wrapper` and // we would like to create a member or local variable while obeying the request -// for the reference-wrapper represents. As arguments may come potentially -// cv-qualified, as well as references we need to first decay them to remove -// cv-qualification, reference and/or turn arrays into a pointer etc. (see -// `bsl::decay`). When the argument type decays into a reference wrapper we +// for the reference type that the reference-wrapper represents. As parameters +// may be cv-qualified and may be references we need to first decay them (see +// `bsl::decay`). When the argument type decays into a reference-wrapper we // want to use a reference to the wrapped type, and simply use the decayed -// variations of the unwrapped types. This is a use case for +// variations of types that are not wrapped. This is a use case for // `bsl::unwrap_ref_decay`. // // First, we create types that may be the bases for reference-wrapped, and @@ -147,12 +146,12 @@ BSLS_IDENT("$Id: $") #include #if BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY - #include // 'std::unwrap_reference', 'std::unwrap_reference_t' + #include // 'std::unwrap_reference', 'std::unwrap_reference_t' #endif - // ====================== - // struct uwrap_reference - // ====================== + // ======================= + // struct unwrap_ref_decay + // ======================= namespace bsl { @@ -163,11 +162,10 @@ using std::unwrap_ref_decay_t; /// This `struct` template implements the `unwrap_ref_decay` meta-function /// defined in the C++20 standard [meta.trans.other], providing an alias, -/// `type`, that returns the result. `type` has the same type as the -/// (template parameter) `t_TYPE` unless `bsl::decay::type` is a -/// specialization of `bsl::reference_wrapper` (which is an alias to -/// `std::reference_wrapper` when that exists) for a type `U`, in which case -/// `type` shall be `U&`. +/// `type`, that returns the result. `type` is `bsl::decay::type` +/// unless `bsl::decay::type` is a specialization of +/// `bsl::reference_wrapper` (which is an alias to `std::reference_wrapper` +/// when that exists) for a type `U`, in which case `type` shall be `U&`. template struct unwrap_ref_decay { // TYPES @@ -183,9 +181,9 @@ struct unwrap_ref_decay { /// 'bsl::unwrap_ref_decay' meta-function. template using unwrap_ref_decay_t = typename unwrap_ref_decay::type; -#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES +#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES -#endif // else of BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY +#endif // else of BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY } // close namespace bsl diff --git a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp index 1748616b79..2281c36433 100644 --- a/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwraprefdecay.t.cpp @@ -26,12 +26,12 @@ using namespace BloombergLP; // Overview // -------- // The component under test defines a meta-function `bsl::unwrap_ref_decay` -// that decays its template `TYPE` argument then it unwraps it if it is a -// reference wrapper specialization `bsl::reference_wrapper` (which is an +// that decays its template `TYPE` argument then unwraps it if it is a +// reference-wrapper specialization `bsl::reference_wrapper` (which is an // alias to `std::reference_wrapper` when that exists) by providing a `type` -// member with the type `U&`. If the specified `TYPE` does not decay into a -// specialization of either reference wrapper the member `type` shall be the -// decayed `TYPE`. +// member with the type `U&`. If the specified `t_TYPE` does not decay into a +// specialization of the reference-wrapper the member `type` will be the +// decayed `t_TYPE`. // // The component also defines an alias to the result type of the // `bsl::unwrap_ref_decay` meta-function. Thus, we need to ensure that the @@ -306,8 +306,7 @@ int main(int argc, char *argv[]) // // Concerns: // 1. `unwrap_ref_decay::type` is `U&` for any template type argument - // that decays (`bsl::decay`) into `bsl::reference_wrapper` or - // `std::reference_wrapper`. + // that decays (`bsl::decay`) into `bsl::reference_wrapper`. // // 2. `unwrap_ref_decay` does not transform `TYPE` when `TYPE` does not // decay into a reference-wrapper type. @@ -361,7 +360,7 @@ int main(int argc, char *argv[]) // Arrays decay into pointers so the wrapper should not be unwrapped typedef bsl::reference_wrapper WrappedType; - ASSERT_UNWRAP_REF(WrappedType[], WrappedType*); + ASSERT_UNWRAP_REF(WrappedType[], WrappedType*); ASSERT_UNWRAP_REF(FuncType, FuncType*); ASSERT_UNWRAP_REF(Enum, Enum); @@ -374,25 +373,15 @@ int main(int argc, char *argv[]) #ifdef BSLS_LIBRARYFEATURES_HAS_CPP20_BASELINE_LIBRARY #define ASSERT_UNWRAP_REF_WRAPPED(TYPE, RESULT) \ ASSERT_UNWRAP_REF(bsl::reference_wrapper, RESULT); \ - ASSERT_UNWRAP_REF(std::reference_wrapper, RESULT); \ ASSERT_UNWRAP_REF(bsl::reference_wrapper&, RESULT); \ - ASSERT_UNWRAP_REF(std::reference_wrapper&, RESULT); \ ASSERT_UNWRAP_REF(const bsl::reference_wrapper, RESULT); \ - ASSERT_UNWRAP_REF(const std::reference_wrapper, RESULT); \ ASSERT_UNWRAP_REF(const bsl::reference_wrapper&, RESULT); \ - ASSERT_UNWRAP_REF(const std::reference_wrapper&, RESULT); \ ASSERT_UNWRAP_REF(volatile bsl::reference_wrapper, RESULT); \ - ASSERT_UNWRAP_REF(volatile std::reference_wrapper, RESULT); \ ASSERT_UNWRAP_REF(volatile bsl::reference_wrapper&, RESULT); \ - ASSERT_UNWRAP_REF(volatile std::reference_wrapper&, RESULT); \ ASSERT_UNWRAP_REF(const volatile bsl::reference_wrapper, \ RESULT); \ - ASSERT_UNWRAP_REF(const volatile std::reference_wrapper, \ - RESULT); \ ASSERT_UNWRAP_REF(const volatile bsl::reference_wrapper&, \ - RESULT); \ - ASSERT_UNWRAP_REF(const volatile std::reference_wrapper&, \ - RESULT) + RESULT) #else #define ASSERT_UNWRAP_REF_WRAPPED(TYPE, RESULT) \ ASSERT_UNWRAP_REF(bsl::reference_wrapper, RESULT); \ diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.h b/groups/bsl/bslmf/bslmf_unwrapreference.h index 3a2f2b158e..d4a8b026ed 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.h +++ b/groups/bsl/bslmf/bslmf_unwrapreference.h @@ -13,12 +13,12 @@ BSLS_IDENT("$Id: $") // //@CANONICAL_HEADER: bsl_functional.h, bsl_type_traits.h // -//@SEE_ALSO: bslmf_referencewrapper, bslmf_uwrap_ref_decay +//@SEE_ALSO: bslmf_referencewrapper, bslmf_unwrap_ref_decay // //@DESCRIPTION: This component defines a meta-function `bsl::unwrap_reference` // that may be used to unwrap a `bsl::reference_wrapper` (which is an alias of // `std::reference_wrapper` when that exists) of some type `U`, resulting in -// `U&`. In case the specified type template argument is not an specialization +// `U&`. In case the specified type template argument is not a specialization // of `bsl::reference_wrapper` the result is the type itself. // // `bsl::unwrap_reference` meets the requirements of the `unwrap_reference` @@ -67,9 +67,9 @@ BSLS_IDENT("$Id: $") #include // 'std::unwrap_reference', 'std::unwrap_reference_t' #endif - // ====================== - // struct uwrap_reference - // ====================== + // ======================= + // struct unwrap_reference + // ======================= namespace bsl { @@ -96,7 +96,6 @@ struct unwrap_reference { /// is a `bsl::reference_wrapper`. template struct unwrap_reference > { - // TYPES /// This `typedef` is an alias to the template parameter `t_WRAPPED_TYPE&`. diff --git a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp index d66ad041f8..e0f7065145 100644 --- a/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp +++ b/groups/bsl/bslmf/bslmf_unwrapreference.t.cpp @@ -28,9 +28,9 @@ using namespace BloombergLP; // The component under test defines a meta-function `bsl::unwrap_reference` // that unwraps a reference wrapper specialization `bsl::reference_wrapper` // (which is an alias to `std::reference_wrapper` when that exists) template -// `TYPE` argument by providing a `type` member with the type `U&`. If the -// specified `TYPE` is not a specialization of either reference wrapper the -// member `type` shall be `TYPE`. +// `t_TYPE` argument by providing a `type` member with the type `U&`. If the +// specified `t_TYPE` is not a specialization of either reference wrapper the +// member `type` will be `t_TYPE`. // // The component also defines an alias to the result type of the // `bsl::unwrap_reference` meta-function. Thus, we need to ensure that the @@ -101,6 +101,8 @@ class Class {}; enum Enum {}; union Union {}; +template