// bslmf_istriviallycopyable.h -*-C++-*- #ifndef INCLUDED_BSLMF_ISTRIVIALLYCOPYABLE #define INCLUDED_BSLMF_ISTRIVIALLYCOPYABLE #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a meta-function for determining trivially copyable types. // //@CLASSES: // bsl::is_trivially_copyable: type-traits meta-function // bsl::is_trivially_copyable_v: the result value of the meta-function // //@SEE_ALSO: bslmf_integralconstant, bslmf_nestedtraitdeclaration // //@DESCRIPTION: This component defines a meta-function, // 'bsl::is_trivially_copyable' and a template variable // 'bsl::is_trivially_copyable_v', that represents the result value of the // 'bsl::is_trivially_copyable' meta-function, that may be used to query // whether a type is trivially copyable as defined in section 3.9.3 of the // C++11 standard [basic.types]. // // 'bsl::is_trivially_copyable' has the same syntax as the // 'is_trivially_copyable' template from the C++11 standard [meta.unary.prop]. // However, unlike the template defined in the C++11 standard, which can // determine the correct value for all types without requiring specialization, // 'bsl::is_trivially_copyable' can, by default, determine the value for the // following type categories only: //.. // Type Category Is Trivially Copyable // ------------- --------------------- // reference types false // fundamental types true // enumerated types true // pointers true // pointers to members true //.. // For all other types, 'bsl::is_trivially_copyable' returns 'false', unless // the type is explicitly specified to be trivially copyable. This can be done // in 2 ways: // //: 1 Define a template specialization for 'bsl::is_trivially_copyable' having //: the type as the template parameter that inherits directly from //: 'bsl::true_type'. //: //: 2 Use the 'BSLMF_NESTED_TRAIT_DECLARATION' macro to define //: 'bsl::is_trivially_copyable' as a trait in the class definition of the //: type. // // Note that the template variable 'is_trivially_copyable_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_trivially_copyable_v' is // defined as an 'inline constexpr bool' variable. Otherwise, if the compiler // supports the variable templates C++14 compiler feature, // 'bsl::is_trivially_copyable_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. // ///Usage ///----- // In this section we show intended use of this component. // ///Example 1: Verify Whether Types are Trivially Copyable /// - - - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose that we want to assert whether a type is trivially copyable. // // First, we define a set of types to evaluate: //.. // typedef int MyFundamentalType; // typedef int& MyFundamentalTypeReference; // // class MyTriviallyCopyableType { // }; // // struct MyNonTriviallyCopyableType { // //... // }; //.. // Then, since user-defined types cannot be automatically evaluated by // 'is_trivially_copyable', we define a template specialization to specify that // 'MyTriviallyCopyableType' is trivially copyable: //.. // namespace bsl { // // template <> // struct is_trivially_copyable<MyTriviallyCopyableType> : bsl::true_type { // // This template specialization for 'is_trivially_copyable' indicates // // that 'MyTriviallyCopyableType' is a trivially copyable type. // }; // // } // close namespace bsl //.. // Now, we verify whether each type is trivially copyable using // 'bsl::is_trivially_copyable': //.. // assert(true == bsl::is_trivially_copyable<MyFundamentalType>::value); // assert(false == bsl::is_trivially_copyable< // MyFundamentalTypeReference>::value); // assert(true == bsl::is_trivially_copyable< // MyTriviallyCopyableType>::value); // assert(false == bsl::is_trivially_copyable< // MyNonTriviallyCopyableType>::value); //.. // Note that if the current compiler supports the variable templates C++14 // feature, then we can re-write the snippet of code above as follows: //.. // #ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES // assert(true == bsl::is_trivially_copyable_v<MyFundamentalType>); // assert(false == bsl::is_trivially_copyable_v<MyFundamentalTypeReference>); // assert(true == bsl::is_trivially_copyable_v<MyTriviallyCopyableType>); // assert(false == bsl::is_trivially_copyable_v<MyNonTriviallyCopyableType>); // #endif //.. #include <bslscm_version.h> #include <bslmf_detectnestedtrait.h> #include <bslmf_integralconstant.h> #include <bslmf_isenum.h> #include <bslmf_isfundamental.h> #include <bslmf_ismemberpointer.h> #include <bslmf_ispointer.h> #include <bslmf_voidtype.h> #include <bsls_compilerfeatures.h> #include <bsls_keyword.h> #include <bsls_platform.h> #ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <bsls_timeinterval.h> // see DRQS 131017375 #endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES #include <stddef.h> #ifdef 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 #ifdef BSLS_COMPILERFEATURES_SUPPORT_TRAITS_HEADER #define BSLMF_ISTRIVIALLYCOPYABLE_NATIVE_IMPLEMENTATION // Early implementations of C++11 type traits did not always provide the // necessary compiler intrinsic to detect the 'trivial' traits, so we use an // additional component-level feature macro to detect whether native support is // truly present. This macro is defined for Visual C++ prior to VC2015 due to // wrong results for certain types with the initial implementation of that // trait. #if (defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION < 50000) \ || (defined(BSLS_PLATFORM_CMP_MSVC) && BSLS_PLATFORM_CMP_VERSION < 1900) # undef BSLMF_ISTRIVIALLYCOPYABLE_NATIVE_IMPLEMENTATION #endif #endif namespace bsl { template <class t_TYPE> struct is_trivially_copyable; #ifdef BSLS_COMPILERFEATURES_SUPPORT_VARIABLE_TEMPLATES template <class t_TYPE> BSLS_KEYWORD_INLINE_VARIABLE constexpr bool is_trivially_copyable_v = is_trivially_copyable<t_TYPE>::value; // This template variable represents the result value of the // 'bsl::is_trivially_copyable' meta-function. #endif } // close namespace bsl namespace BloombergLP { namespace bsls { class TimeInterval; } namespace bslmf { struct Nil; // ============================== // struct IsTriviallyCopyable_Imp // ============================== template <class t_TYPE, bool t_K_INTRINSIC = false> struct IsTriviallyCopyable_DetectTrait : DetectNestedTrait<t_TYPE, bsl::is_trivially_copyable>::type { // This 'struct' template implements a meta-function to determine whether // the (non-cv-qualified) (template parameter) 't_TYPE' has been explicitly // tagged with the trivially copyable trait. If the flag 't_K_INTRINSIC' // is 'true' then the compiler has already determined that 't_TYPE' is // trivially copyable without user intervention, and the check for nested // traits can be optimized away. }; template <class t_TYPE> struct IsTriviallyCopyable_DetectTrait<t_TYPE, true> : bsl::true_type { // This 'struct' template implements a meta-function to determine whether // the (non-cv-qualified) (template parameter) 't_TYPE' is trivially // copyable. }; #ifdef BSLMF_ISTRIVIALLYCOPYABLE_NATIVE_IMPLEMENTATION template <class t_TYPE> struct IsTriviallyCopyable_Intrinsic : IsTriviallyCopyable_DetectTrait< t_TYPE, ::std::is_trivially_copyable<t_TYPE>::value>::type { // This 'struct' template implements a meta-function to determine whether // the (non-cv-qualified) (template parameter) 't_TYPE' is trivially // copyable. }; #else template <class t_TYPE> struct IsTriviallyCopyable_Intrinsic : IsTriviallyCopyable_DetectTrait< t_TYPE, bsl::is_fundamental<t_TYPE>::value || bsl::is_enum<t_TYPE>::value || bsl::is_pointer<t_TYPE>::value || bsl::is_member_pointer<t_TYPE>::value>::type { // This 'struct' template implements a meta-function to determine whether // the (non-cv-qualified) (template parameter) 't_TYPE' is trivially // copyable. Without compiler support, only scalar types are trivial // copyable. }; template <> struct IsTriviallyCopyable_Intrinsic<void> : bsl::false_type { // This explicit specialization reports that 'void' is not a trivially // copyable type, despite being a fundamental type. }; #endif #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130 template <class NON_CV_TYPE, class = void> struct IsTriviallyCopyable_Solaris : bsl::false_type { // The Solaris CC compiler (prior to CC 12.4) will match certain types, // such as abominable function types, as matching a 'cv'-qualified type in // partial specialization, even when that type is not 'cv'-qualified. The // idiom of implementing a partial specialization for 'cv'-qualified traits // in terms of the primary template then becomes infinitely recursive for // those special cases, so we provide a shim implementation class to handle // the delegation. This primary template always derives from 'false_type', // and will be matched for function types, reference types, and 'void', // none of which are trivially copyable. The partial specialization below // handles recursion back to the primary trait for all other types. }; template <class NON_CV_TYPE> struct IsTriviallyCopyable_Solaris<NON_CV_TYPE, BSLMF_VOIDTYPE(NON_CV_TYPE[])> : bsl::is_trivially_copyable<NON_CV_TYPE>::type { }; #endif } // close package namespace } // close enterprise namespace namespace bsl { // ============================ // struct is_trivially_copyable // ============================ template <class t_TYPE> struct is_trivially_copyable : BloombergLP::bslmf::IsTriviallyCopyable_Intrinsic<t_TYPE>::type { // This 'struct' template implements a meta-function to determine whether // the (template parameter) 't_TYPE' is trivially copyable. This 'struct' // derives from 'bsl::true_type' if the 't_TYPE' is trivially copyable, and // from 'bsl::false_type' otherwise. This meta-function has the same // syntax as the 'is_trivially_copyable' meta-function defined in the C++11 // standard [meta.unary.prop]; however, this meta-function can // automatically determine the value for the following types only: // reference types, fundamental types, enumerated types, pointers to // members, and types declared to have the 'bsl::is_trivially_copyable' // trait using the 'BSLMF_NESTED_TRAIT_DECLARATION' macro (the value for // other types defaults to 'false'). To support other trivially copyable // types, this template must be specialized to inherit from // 'bsl::true_type' for them. }; template <class t_TYPE> struct is_trivially_copyable<t_TYPE&> : false_type { // This partial specialization optimizes away a number of nested template // instantiations to prove that reference types are never trivially // copyable. }; #if defined(BSLS_COMPILERFEATURES_SUPPORT_RVALUE_REFERENCES) template <class t_TYPE> struct is_trivially_copyable<t_TYPE&&> : false_type { // This partial specialization optimizes away a number of nested template // instantiations to prove that reference types are never trivially // copyable. }; #endif #if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130 // Solaris CC compiler will erroneously match a cv-qualified abominable // function type with a partial specialization for cv-qualified types, and then // infinitely recurse when the cv-qualifier is not stripped when instantiating // the base class. As this is only a problem for abominable function types // that are never trivially copyable, the following workaround (preserving lazy // evaluation of the recursive template instantiation) is ugly, but suffices. // Compiler fix verified for the CC 12.4 compiler. template <class t_TYPE> struct is_trivially_copyable<const t_TYPE> : BloombergLP::bslmf::IsTriviallyCopyable_Solaris<t_TYPE>::type { // This partial specialization ensures that const-qualified types have the // same result as their element type. }; template <class t_TYPE> struct is_trivially_copyable<volatile t_TYPE> : BloombergLP::bslmf::IsTriviallyCopyable_Solaris<t_TYPE>::type { // This partial specialization ensures that volatile-qualified types have // the same result as their element type. }; template <class t_TYPE> struct is_trivially_copyable<const volatile t_TYPE> : BloombergLP::bslmf::IsTriviallyCopyable_Solaris<t_TYPE>::type { // This partial specialization ensures that const-volatile-qualified types // have the same result as their element type. }; #else template <class t_TYPE> struct is_trivially_copyable<const t_TYPE> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that const-qualified types have the // same result as their element type. }; template <class t_TYPE> struct is_trivially_copyable<volatile t_TYPE> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that volatile-qualified types have // the same result as their element type. }; template <class t_TYPE> struct is_trivially_copyable<const volatile t_TYPE> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that const-volatile-qualified types // have the same result as their element type. }; #endif template <class t_TYPE, size_t t_LEN> struct is_trivially_copyable<t_TYPE[t_LEN]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that array types have the same // result as their element type. }; template <class t_TYPE, size_t t_LEN> struct is_trivially_copyable<const t_TYPE[t_LEN]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that const-qualified array types // have the same result as their element type. }; template <class t_TYPE, size_t t_LEN> struct is_trivially_copyable<volatile t_TYPE[t_LEN]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that volatile-qualified array types // have the same result as their element type. }; template <class t_TYPE, size_t t_LEN> struct is_trivially_copyable<const volatile t_TYPE[t_LEN]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that const-volatile-qualified array // types have the same result as their element type. }; #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_trivially_copyable<t_TYPE[]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that array-of-unknown-bound types // have the same result as their element type. }; template <class t_TYPE> struct is_trivially_copyable<const t_TYPE[]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that const-qualified // array-of-unknown-bound types have the same result as their element type. }; template <class t_TYPE> struct is_trivially_copyable<volatile t_TYPE[]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that volatile-qualified // array-of-unknown-bound types have the same result as their element type. }; template <class t_TYPE> struct is_trivially_copyable<const volatile t_TYPE[]> : is_trivially_copyable<t_TYPE>::type { // This partial specialization ensures that const-volatile-qualified // array-of-unknown-bound types have the same result as their element type. }; #endif ///IMPLEMENTATION NOTE ///------------------- // We specialize 'is_trivially_copyable' for 'bsls::TimeInterval' here because // 'bsls' is levelized below 'bslmf'. Previously, 'bsls_timeinterval.h' had // forward declared the 'is_trivially_copyable' template and provided a // specialization for 'TimeInterval' (see BDE 2.24.0 tag), but the forward // declaration caused compilation errors with the Sun CC 5.13 compiler. // // We specialize 'is_trivially_copyable' for 'bslmf::Nil' here to avoid // increasing the dependency envelope of 'bslmf_nil'. // // Neither of these trait declarations will be needed once we fully migrate to // a C++11 definition for 'is_trivially_copyable'. template <> struct is_trivially_copyable<BloombergLP::bsls::TimeInterval> : bsl::true_type{ // This template specialization for 'is_trivially_copyable' indicates that // 'TimeInterval' is a trivially copyable type. }; #ifndef BSLMF_ISTRIVIALLYCOPYABLE_NATIVE_IMPLEMENTATION template <> struct is_trivially_copyable<BloombergLP::bslmf::Nil> : bsl::true_type { // This template specialization for 'is_trivially_copyable' indicates that // 'Nil' is a trivially copyable type. }; #endif } // close namespace bsl #endif // ! defined(INCLUDED_BSLMF_ISTRIVIALLYCOPYABLE) // ---------------------------------------------------------------------------- // Copyright 2019 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 ----------------------------------