template struct StructExtends { enum { value = false }; }; template struct IsPartOfStructureChain { static const bool valid = false; }; template struct IsPartOfStructureChain { static const bool valid = std::is_same::value || IsPartOfStructureChain::valid; }; template struct StructureChainContains { static const bool value = std::is_same>::type>::value || StructureChainContains::value; }; template struct StructureChainContains<0, T, ChainElements...> { static const bool value = std::is_same>::type>::value; }; template struct StructureChainValidation { using TestType = typename std::tuple_element>::type; static const bool valid = StructExtends>::type>::value && ( TestType::allowDuplicate || !StructureChainContains::value ) && StructureChainValidation::valid; }; template struct StructureChainValidation<0, ChainElements...> { static const bool valid = true; }; template class StructureChain : public std::tuple { // Note: StructureChain has no move constructor or move assignment operator, as it is not supposed to contain movable containers. // In order to get a copy-operation on a move-operations, those functions are neither deleted nor defaulted. public: StructureChain() VULKAN_HPP_NOEXCEPT { static_assert( StructureChainValidation::valid, "The structure chain is not valid!" ); link(); } StructureChain( StructureChain const & rhs ) VULKAN_HPP_NOEXCEPT : std::tuple( rhs ) { static_assert( StructureChainValidation::valid, "The structure chain is not valid!" ); link( &std::get<0>( *this ), &std::get<0>( rhs ), reinterpret_cast( &std::get<0>( *this ) ), reinterpret_cast( &std::get<0>( rhs ) ) ); } StructureChain( ChainElements const &... elems ) VULKAN_HPP_NOEXCEPT : std::tuple( elems... ) { static_assert( StructureChainValidation::valid, "The structure chain is not valid!" ); link(); } StructureChain & operator=( StructureChain const & rhs ) VULKAN_HPP_NOEXCEPT { std::tuple::operator=( rhs ); link( &std::get<0>( *this ), &std::get<0>( rhs ), reinterpret_cast( &std::get<0>( *this ) ), reinterpret_cast( &std::get<0>( rhs ) ) ); return *this; } template >::type, size_t Which = 0> T & get() VULKAN_HPP_NOEXCEPT { return std::get::value>( static_cast &>( *this ) ); } template >::type, size_t Which = 0> T const & get() const VULKAN_HPP_NOEXCEPT { return std::get::value>( static_cast const &>( *this ) ); } template std::tuple get() VULKAN_HPP_NOEXCEPT { return std::tie( get(), get(), get()... ); } template std::tuple get() const VULKAN_HPP_NOEXCEPT { return std::tie( get(), get(), get()... ); } // assign a complete structure to the StructureChain without modifying the chaining template >::type, size_t Which = 0> StructureChain & assign( const T & rhs ) VULKAN_HPP_NOEXCEPT { T & lhs = get(); auto pNext = lhs.pNext; lhs = rhs; lhs.pNext = pNext; return *this; } template typename std::enable_if>::type>::value && ( Which == 0 ), bool>::type isLinked() const VULKAN_HPP_NOEXCEPT { return true; } template typename std::enable_if>::type>::value || ( Which != 0 ), bool>::type isLinked() const VULKAN_HPP_NOEXCEPT { static_assert( IsPartOfStructureChain::valid, "Can't unlink Structure that's not part of this StructureChain!" ); return isLinked( reinterpret_cast( &get() ) ); } template typename std::enable_if>::type>::value || ( Which != 0 ), void>::type relink() VULKAN_HPP_NOEXCEPT { static_assert( IsPartOfStructureChain::valid, "Can't relink Structure that's not part of this StructureChain!" ); auto pNext = reinterpret_cast( &get() ); VULKAN_HPP_ASSERT( !isLinked( pNext ) ); auto & headElement = std::get<0>( static_cast &>( *this ) ); pNext->pNext = reinterpret_cast( headElement.pNext ); headElement.pNext = pNext; } template typename std::enable_if>::type>::value || ( Which != 0 ), void>::type unlink() VULKAN_HPP_NOEXCEPT { static_assert( IsPartOfStructureChain::valid, "Can't unlink Structure that's not part of this StructureChain!" ); unlink( reinterpret_cast( &get() ) ); } private: template struct ChainElementIndex : ChainElementIndex { }; template struct ChainElementIndex::value, void>::type, First, Types...> : ChainElementIndex { }; template struct ChainElementIndex::value, void>::type, First, Types...> : ChainElementIndex { }; template struct ChainElementIndex::value, void>::type, First, Types...> : std::integral_constant { }; bool isLinked( VkBaseInStructure const * pNext ) const VULKAN_HPP_NOEXCEPT { VkBaseInStructure const * elementPtr = reinterpret_cast( &std::get<0>( static_cast const &>( *this ) ) ); while ( elementPtr ) { if ( elementPtr->pNext == pNext ) { return true; } elementPtr = elementPtr->pNext; } return false; } template typename std::enable_if::type link() VULKAN_HPP_NOEXCEPT { auto & x = std::get( static_cast &>( *this ) ); x.pNext = &std::get( static_cast &>( *this ) ); link(); } template typename std::enable_if::type link() VULKAN_HPP_NOEXCEPT { } void link( void * dstBase, void const * srcBase, VkBaseOutStructure * dst, VkBaseInStructure const * src ) { while ( src->pNext ) { std::ptrdiff_t offset = reinterpret_cast( src->pNext ) - reinterpret_cast( srcBase ); dst->pNext = reinterpret_cast( reinterpret_cast( dstBase ) + offset ); dst = dst->pNext; src = src->pNext; } dst->pNext = nullptr; } void unlink( VkBaseOutStructure const * pNext ) VULKAN_HPP_NOEXCEPT { VkBaseOutStructure * elementPtr = reinterpret_cast( &std::get<0>( static_cast &>( *this ) ) ); while ( elementPtr && ( elementPtr->pNext != pNext ) ) { elementPtr = elementPtr->pNext; } if ( elementPtr ) { elementPtr->pNext = pNext->pNext; } else { VULKAN_HPP_ASSERT( false ); // fires, if the ClassType member has already been unlinked ! } } }; // interupt the VULKAN_HPP_NAMESPACE for a moment to add specializations of std::tuple_size and std::tuple_element for the StructureChain! } namespace std { template struct tuple_size> { static constexpr size_t value = std::tuple_size>::value; }; template struct tuple_element> { using type = typename std::tuple_element>::type; }; } // namespace std namespace VULKAN_HPP_NAMESPACE {