// bsltf_allocargumenttype.h -*-C++-*- #ifndef INCLUDED_BSLTF_ALLOCARGUMENTTYPE #define INCLUDED_BSLTF_ALLOCARGUMENTTYPE #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide an allocating test class to represent function arguments. // //@CLASSES: // bsltf::AllocArgumentType<N>: simple wrapper around an allocated 'int' // //@SEE_ALSO: bsltf_argumenttype, bsltf_templatetestfacility // //@DESCRIPTION: This component provides a representation of an allocating // argument type template class, 'bsltf::AllocArgumentType<N>', used for // testing functions that take a variable number of template arguments. The // integer template parameter enables specification of a number of types // without requiring a separate component for each. Note that // default-constructed object of this type does not allocate any memory. Also // note, that copy or move of the default-constructed object also does not // allocate any memory. Copy and move constructors are defined. // ///Attributes ///---------- //.. // Name Type Default // ------------------ ----------- ------- // data int -1 //.. //: o 'data': representation of the class value // ///Usage ///----- // This section illustrates intended use of this component. // // See 'bsltf_argumenttype' for usage example. #include <bslscm_version.h> #include <bsltf_movestate.h> #include <bslma_default.h> #include <bslma_allocator.h> #include <bslma_usesbslmaallocator.h> #include <bslmf_movableref.h> #include <bsls_assert.h> namespace BloombergLP { namespace bsltf { // ============================ // class AllocArgumentType<int> // ============================ template <int N> class AllocArgumentType { // This class template declares a separate type for each template parameter // value 'N', 'bsltf::AllocArgumentType<N>', that wraps an integer value // and provides implicit conversion to and from 'int'. The wrapped integer // will be dynamically allocated using the supplied allocator, or the // default allocator if none is supplied. Its main purpose is that having // separate types for testing enables distinguishing them when calling // through a function template interface, thereby avoiding ambiguities or // accidental switching of arguments in the implementation of in-place // constructors. It further tests that allocators are propagated // correctly, or not, as required. // PRIVATE TYPES typedef bslmf::MovableRefUtil MoveUtil; // DATA bslma::Allocator *d_allocator_p; // allocator used to supply memory // (held, not owned) int *d_data_p; // pointer to the data value MoveState::Enum d_movedFrom; // moved-from state MoveState::Enum d_movedInto; // moved-from state public: // CREATORS explicit AllocArgumentType(bslma::Allocator *basicAllocator = 0); // Create an 'AllocArgumentType' object having the (default) attribute // value '-1'. Optionally specify a 'basicAllocator' used to supply // memory. If 'basicAllocator' is 0, the currently installed default // allocator is used. Note, that default constructor does not allocate // memory. explicit AllocArgumentType(int value, bslma::Allocator *basicAllocator = 0); // Create an 'AllocArgumentType' object having the specified 'value'. // Optionally specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is 0, the currently installed default allocator is // used. The behavior is undefined unless 'value >= 0'. AllocArgumentType(const AllocArgumentType& original, bslma::Allocator *basicAllocator = 0); // Create an 'AllocArgumentType' object having the same value as the // specified 'original'. Optionally specify a 'basicAllocator' used to // supply memory. If 'basicAllocator' is 0, the currently installed // default allocator is used. Note, that no memory is allocated if // 'original' refers to a default-constructed object. AllocArgumentType(bslmf::MovableRef<AllocArgumentType> original); // Create an 'AllocArgumentType' object having the same value as the // specified 'original'. Note, that no memory is allocated if // 'original' refers to a default-constructed object. AllocArgumentType(bslmf::MovableRef<AllocArgumentType> original, bslma::Allocator *basicAllocator); // Create an 'AllocArgumentType' object having the same value as the // specified 'original' using the specified 'basicAllocator' to supply // memory. Note, that no memory is allocated if 'original' refers to a // default-constructed object. ~AllocArgumentType(); // Destroy this object. // MANIPULATORS AllocArgumentType& operator=(const AllocArgumentType& rhs); // Assign to this object the value of the specified 'rhs' object. AllocArgumentType& operator=(BloombergLP::bslmf::MovableRef<AllocArgumentType> rhs); // Assign to this object the value of the specified 'rhs' object. Note // that 'rhs' is left in a valid but unspecified state. // ACCESSORS bslma::Allocator *allocator() const; // Return the allocator used by this object to supply memory. operator int() const; // Return the value of this test argument object. MoveState::Enum movedInto() const; // Return the move state of this object as target of a move operation. MoveState::Enum movedFrom() const; // Return the move state of this object as source of a move operation. }; // FREE FUNCTIONS template <int N> MoveState::Enum getMovedFrom(const AllocArgumentType<N>& object); // Return the move-from state of the specified 'object'. template <int N> MoveState::Enum getMovedInto(const AllocArgumentType<N>& object); // Return the move-into state of the specified 'object'. // ============================================================================ // INLINE AND TEMPLATE FUNCTION IMPLEMENTATIONS // ============================================================================ // -------------------------- // class AllocArgumentType<N> // -------------------------- // CREATORS template <int N> inline AllocArgumentType<N>::AllocArgumentType(bslma::Allocator *basicAllocator) : d_allocator_p(bslma::Default::allocator(basicAllocator)) , d_data_p(0) , d_movedFrom(bsltf::MoveState::e_NOT_MOVED) , d_movedInto(bsltf::MoveState::e_NOT_MOVED) { // Note that the default constructor does not allocate. This is done to // correctly count allocations when not the whole set of arguments is // passed to emplacable test types. } template <int N> inline AllocArgumentType<N>::AllocArgumentType(int value, bslma::Allocator *basicAllocator) : d_allocator_p(bslma::Default::allocator(basicAllocator)) , d_data_p(0) , d_movedFrom(bsltf::MoveState::e_NOT_MOVED) , d_movedInto(bsltf::MoveState::e_NOT_MOVED) { BSLS_ASSERT_SAFE(value >= 0); d_data_p = reinterpret_cast<int *>(d_allocator_p->allocate(sizeof(int))); *d_data_p = value; } template <int N> inline AllocArgumentType<N>::AllocArgumentType( const AllocArgumentType& original, bslma::Allocator *basicAllocator) : d_allocator_p(bslma::Default::allocator(basicAllocator)) , d_data_p(0) , d_movedFrom(bsltf::MoveState::e_NOT_MOVED) , d_movedInto(bsltf::MoveState::e_NOT_MOVED) { if (original.d_data_p) { d_data_p = reinterpret_cast<int *>( d_allocator_p->allocate(sizeof(int))); *d_data_p = int(original); } } template <int N> inline AllocArgumentType<N>::AllocArgumentType( bslmf::MovableRef<AllocArgumentType> original) : d_allocator_p(MoveUtil::access(original).d_allocator_p) , d_movedFrom(bsltf::MoveState::e_NOT_MOVED) , d_movedInto(bsltf::MoveState::e_MOVED) { AllocArgumentType& lvalue = original; d_data_p = lvalue.d_data_p; lvalue.d_data_p = 0; lvalue.d_movedInto = bsltf::MoveState::e_NOT_MOVED; lvalue.d_movedFrom = bsltf::MoveState::e_MOVED; } template <int N> inline AllocArgumentType<N>::AllocArgumentType( bslmf::MovableRef<AllocArgumentType> original, bslma::Allocator *basicAllocator) : d_allocator_p(bslma::Default::allocator(basicAllocator)) , d_movedFrom(bsltf::MoveState::e_NOT_MOVED) , d_movedInto(bsltf::MoveState::e_MOVED) { AllocArgumentType& lvalue = original; if (d_allocator_p == lvalue.d_allocator_p) { d_data_p = lvalue.d_data_p; lvalue.d_data_p = 0; } else { if (lvalue.d_data_p) { d_data_p = reinterpret_cast<int *>( d_allocator_p->allocate(sizeof(int))); *d_data_p = int(lvalue); *lvalue.d_data_p = -1; } else { d_data_p = 0; } } lvalue.d_movedInto = bsltf::MoveState::e_NOT_MOVED; lvalue.d_movedFrom = bsltf::MoveState::e_MOVED; } template <int N> inline AllocArgumentType<N>::~AllocArgumentType() { if (d_data_p) { d_allocator_p->deallocate(d_data_p); } } // MANIPULATORS template <int N> inline AllocArgumentType<N>& AllocArgumentType<N>::operator=(const AllocArgumentType& rhs) { if (this != &rhs) { int *newValue = 0; if (rhs.d_data_p) { newValue = reinterpret_cast<int *>( d_allocator_p->allocate(sizeof(int))); *newValue = int(rhs); } if (d_data_p) { d_allocator_p->deallocate(d_data_p); } d_data_p = newValue; d_movedInto = bsltf::MoveState::e_NOT_MOVED; d_movedFrom = bsltf::MoveState::e_NOT_MOVED; } return *this; } template <int N> inline AllocArgumentType<N>& AllocArgumentType<N>::operator=( BloombergLP::bslmf::MovableRef<AllocArgumentType> rhs) { AllocArgumentType& lvalue = rhs; if (this != &lvalue) { if (d_allocator_p == lvalue.d_allocator_p) { if (d_data_p) { d_allocator_p->deallocate(d_data_p); } d_data_p = lvalue.d_data_p; lvalue.d_data_p = 0; } else { int *newValue = 0; if (lvalue.d_data_p) { newValue = reinterpret_cast<int *>( d_allocator_p->allocate(sizeof(int))); *newValue = int(lvalue); *lvalue.d_data_p = -1; } if (d_data_p) { d_allocator_p->deallocate(d_data_p); } d_data_p = newValue; } d_movedInto = bsltf::MoveState::e_MOVED; d_movedFrom = bsltf::MoveState::e_NOT_MOVED; lvalue.d_movedInto = bsltf::MoveState::e_NOT_MOVED; lvalue.d_movedFrom = bsltf::MoveState::e_MOVED; } return *this; } // ACCESSORS template <int N> inline AllocArgumentType<N>::operator int() const { return d_data_p ? *d_data_p : -1; } template <int N> inline bslma::Allocator * AllocArgumentType<N>::allocator() const { return d_allocator_p; } template <int N> inline MoveState::Enum AllocArgumentType<N>::movedFrom() const { return d_movedFrom; } template <int N> inline MoveState::Enum AllocArgumentType<N>::movedInto() const { return d_movedInto; } // Aspects // FREE FUNCTIONS template <int N> inline MoveState::Enum getMovedFrom(const AllocArgumentType<N>& object) { return object.movedFrom(); } template <int N> inline MoveState::Enum getMovedInto(const AllocArgumentType<N>& object) { return object.movedInto(); } } // close package namespace // TRAITS namespace bslma { template <int N> struct UsesBslmaAllocator<bsltf::AllocArgumentType<N> > : bsl::true_type {}; } // close namespace bslma } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2016 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 ----------------------------------