// bslmf_iscopyconstructible.h -*-C++-*- #ifndef INCLUDED_BSLMF_ISCOPYCONSTRUCTIBLE #define INCLUDED_BSLMF_ISCOPYCONSTRUCTIBLE #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a meta-function to report if a type is copy constructible. // //@CLASSES: // bsl::is_copy_constructible: type-traits meta-function // bsl::is_copy_constructible_v: the result value of the meta-function // //@SEE_ALSO: bslmf_integralconstant, bslmf_nestedtraitdeclaration // //@DESCRIPTION: This component defines a meta-function, // 'bsl::is_copy_constructible' and a template variable // 'bsl::is_copy_constructible_v', that represents the result value of the // 'bsl::is_copy_constructible' meta-function, that may be used to query // whether a type is copy constructible. // // 'bsl::is_copy_constructible' has the same syntax as the // 'is_copy_constructible' template from the C++11 standard [meta.unary.prop]. // Indeed, in C++11 compilation environments, 'bsl::is_copy_constructible' // simply forwards to the native implementation, which can determine the // correct value for all types without requiring specialization; in C++03 // environments, 'bsl::is_copy_construcible' provides welcome backward // compatibility but returns 'true' for all user-defined types and requires // explicit specialization for types that are not copy constructible (e.g., // move-only types). // // Note that the 'bsl::is_copy_constructible' trait cannot be declared as a // nested trait because the default value of the trait is 'true' and nested // traits work properly only for traits that have default value 'false'. In // order to indicate that a certain type 'T' is not copy constructible, the // following idiom should be used: //.. // namespace bsl { // template <> // struct is_copy_constructible<T> : false_type { }; // } //.. // Also note that the template variable 'is_copy_constructible_v' is defined in // the C++17 standard as an inline variable. If the current compiler supports // the inline variable C++17 compiler feature, 'bsl::is_copy_constructible_v' // is defined as an 'inline constexpr bool' variable. Otherwise, if the // compiler supports the variable templates C++14 compiler feature, // 'bsl::is_copy_constructible_v' is defined as a non-inline 'constexpr bool' // variable. See 'BSLS_COMPILERFEATURES_SUPPORT_INLINE_VARIABLES' and // 'BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES' macros in // bsls_compilerfeatures component for details. #include <bslscm_version.h> #include <bslmf_detectnestedtrait.h> #include <bslmf_integralconstant.h> #include <bslmf_isarray.h> #include <bslmf_isfunction.h> #include <bslmf_isreference.h> #include <bslmf_isvolatile.h> #include <bslmf_istriviallycopyable.h> #include <bsls_compilerfeatures.h> #include <bsls_keyword.h> #if defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER) # include <type_traits> #endif // BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER #ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <bsls_nativestd.h> #endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #if defined(BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER) # define BSLS_ISCOPYCONSTRUCTIBLE_USE_NATIVE_TRAIT 1 #endif namespace bsl { // ============================ // struct is_copy_constructible // ============================ template <class t_TYPE> struct is_copy_constructible; // This 'struct' template implements a meta-function to determine whether // the (template parameter) 't_TYPE' is copy constructible. This 'struct' // derives from 'bsl::true_type' if the 't_TYPE' is copy constructible, and // from 'bsl::false_type' otherwise. This meta-function has the same // syntax as the 'is_copy_constructible' meta-function defined in the C++11 // standard [meta.unary.prop]; on C++03 platforms, however, this // meta-function defaults to 'true_type' for all types that are not // explicitly declared to have the 'bslmf::IsNonCopyable' trait using the // 'BSLMF_NESTED_TRAIT_DECLARATION' macro. To mark a type as non-copyable, // 'bslmf::IsNonCopyable' must be specialized (for that type) to inherit // from 'bsl::true_type'. } // close namespace bsl // ============================================================================ // CLASS TEMPLATE DEFINITIONS // ============================================================================ #if defined(BSLS_ISCOPYCONSTRUCTIBLE_USE_NATIVE_TRAIT) namespace bsl { // ==================================== // struct is_copy_constructible (C++11) // ==================================== ///Implementation Notes ///-------------------- // In C++20 certain array types which decay to their element type, such as // 'const void*' and 'bool', report as copy constructible through // 'std::is_copy_constructible'. In fact, initialization that attempts such // copy constructions does not result in a copy of the original array but // instead initializes only the first element of the new array -- and that is // set to the address of the original array, not the original's first element. // // This behavior has been observed in 'gcc-11' targeting C++20 and should occur // with any compiler correctly supporting C++20 aggregate initialization with // parenthesis (identified by the feature test macro // '__cpp_aggregate_paren_init'). // // An LWG issue (https://wg21.link/lwg####) has been filed to correct this // behavior and continue to return 'false' for all array types. // // The implementation below preemptively implements the expected resolution of // that issue on all platforms. template <class t_TYPE> struct is_copy_constructible : bsl::integral_constant<bool, (bsl::is_array<t_TYPE>::value ? false : std::is_copy_constructible<t_TYPE>::value)> { // This specialization largely defers to the native trait on supported // C++11 compilers. See {Implementation Notes} above. }; #ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES template <class t_TYPE> BSLS_KEYWORD_INLINE_VARIABLE constexpr bool is_copy_constructible_v = is_copy_constructible<t_TYPE>::value; // This template variable represents the result value of the // 'bsl::is_copy_constructible' meta-function. #endif } // close namespace bsl #else namespace BloombergLP { namespace bslmf { // ============================== // struct IsCopyConstructible_Imp // ============================== template <class t_TYPE> struct IsCopyConstructible_Imp : bsl::integral_constant<bool, bsl::is_trivially_copyable<t_TYPE>::value || bsl::is_reference<t_TYPE>::value || !(bsl::is_volatile<t_TYPE>::value || bsl::is_function<t_TYPE>::value)> { // This 'struct' template implements a meta-function to determine whether // the (non-cv-qualified) (template parameter) 't_TYPE' has a copy // constructor. }; template <> struct IsCopyConstructible_Imp<void> : bsl::false_type { // This explicit specialization reports that 'void' does not have a copy // constructor, despite being a fundamental type. }; template <> struct IsCopyConstructible_Imp<volatile void> : bsl::false_type { // This explicit specialization reports that 'volatile void' does not have // a copy constructor, despite being a fundamental type. }; template <class t_TYPE> struct IsCopyConstructible_Imp<t_TYPE *volatile> : bsl::true_type { // This explicit specialization reports that volatile pointer objects have // a copy constructor, just like a fundamental type. }; } // close package namespace } // close enterprise namespace namespace bsl { // ==================================== // struct is_copy_constructible (C++03) // ==================================== template <class t_TYPE> struct is_copy_constructible : BloombergLP::bslmf::IsCopyConstructible_Imp<t_TYPE>::type { // The primary template for this traits handles only non-'const'-qualified // types; partial specializations will handle some interesting cases, // including the remaining 'const'-qualified types. }; template <class t_TYPE> struct is_copy_constructible<const t_TYPE> : is_copy_constructible<t_TYPE>::type { // This partial specialization ensures that const-qualified types have the // same result as their element type. }; template <class t_TYPE, size_t t_LEN> struct is_copy_constructible<t_TYPE[t_LEN]> : false_type { // This partial specialization ensures that array types have the result // 'false'. }; template <class t_TYPE, size_t t_LEN> struct is_copy_constructible<const t_TYPE[t_LEN]> : false_type { // This partial specialization ensures that const-qualified array types // have result 'false'. }; template <class t_TYPE, size_t t_LEN> struct is_copy_constructible<volatile t_TYPE[t_LEN]> : false_type { // This partial specialization ensures that volatile-qualified array types // have the result 'false'. }; template <class t_TYPE, size_t t_LEN> struct is_copy_constructible<const volatile t_TYPE[t_LEN]> : false_type { // This partial specialization ensures that const-volatile-qualified array // types have the result false. }; #if !defined(BSLS_PLATFORM_CMP_IBM) // Last checked with the xlC 12.1 compiler. The IBM xlC compiler has problems // correctly handling arrays of unknown bound as template parameters. template <class t_TYPE> struct is_copy_constructible<t_TYPE[]> : false_type { // This partial specialization ensures that array-of-unknown-bound types // have the result 'false'. }; template <class t_TYPE> struct is_copy_constructible<const t_TYPE[]> : false_type { // This partial specialization ensures that const-qualified // array-of-unknown-bound types have the result 'false'. }; template <class t_TYPE> struct is_copy_constructible<volatile t_TYPE[]> : false_type { // This partial specialization ensures that volatile-qualified // array-of-unknown-bound types have the result 'false'. }; template <class t_TYPE> struct is_copy_constructible<const volatile t_TYPE[]> : false_type { // This partial specialization ensures that const-volatile-qualified // array-of-unknown-bound types have the result 'false'. }; #endif // defined(BSLS_PLATFORM_CMP_IBM) } // close namespace bsl #endif // defined(BSLS_ISCOPYCONSTRUCTIBLE_USE_NATIVE_TRAIT) #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 ----------------------------------