From 5df998c0d6347edd1df76f95e304080f8c0b6f61 Mon Sep 17 00:00:00 2001 From: phantom10111 Date: Fri, 15 Apr 2022 17:17:44 +0200 Subject: [PATCH 1/2] Add ArrayProxy constructors with support for raw array with size There's a little known C language family feature, which makes it possible to take a pointer or reference to an array with size. Use this feature to add constructors to ArrayProxy and ArrayProxyNoTemporaries which can wrap raw arrays and deduce their size automatically. --- README.md | 4 ++++ VulkanHppGenerator.cpp | 30 ++++++++++++++++++++++++++++++ vulkan/vulkan.hpp | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/README.md b/README.md index ac81501..a23c802 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,10 @@ c.setScissor(0, scissorRect); // pass a temporary value. c.setScissor(0, { { 0, 0 },{ 640, 480 } }); +// pass a fixed size array +vk::Rect2D scissorRects[2] = { { { 0, 0 }, { 320, 240 } }, { { 320, 240 }, { 320, 240 } } }; +c.setScissor(0, scissorRects); + // generate a std::initializer_list using two rectangles from the stack. This might generate a copy of the rectangles. vk::Rect2D scissorRect1 = { { 0, 0 },{ 320, 240 } }; vk::Rect2D scissorRect2 = { { 320, 240 },{ 320, 240 } }; diff --git a/VulkanHppGenerator.cpp b/VulkanHppGenerator.cpp index 8d756b6..1a8bb35 100644 --- a/VulkanHppGenerator.cpp +++ b/VulkanHppGenerator.cpp @@ -14851,6 +14851,18 @@ int main( int argc, char ** argv ) , m_ptr( ptr ) {} + template + ArrayProxy( T (& ptr)[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + {} + + template ::value, int>::type = 0> + ArrayProxy( typename std::remove_const::type (& ptr)[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + {} + # if __GNUC__ >= 9 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Winit-list-lifetime" @@ -14986,6 +14998,24 @@ int main( int argc, char ** argv ) , m_ptr( ptr ) {} + template + ArrayProxyNoTemporaries( T (& ptr)[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + {} + + template + ArrayProxyNoTemporaries( T (&& ptr)[C] ) = delete; + + template ::value, int>::type = 0> + ArrayProxyNoTemporaries( typename std::remove_const::type (& ptr)[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + {} + + template ::value, int>::type = 0> + ArrayProxyNoTemporaries( typename std::remove_const::type (&& ptr)[C] ) = delete; + ArrayProxyNoTemporaries( std::initializer_list const & list ) VULKAN_HPP_NOEXCEPT : m_count( static_cast( list.size() ) ) , m_ptr( list.begin() ) diff --git a/vulkan/vulkan.hpp b/vulkan/vulkan.hpp index c10a4f8..3de26fc 100644 --- a/vulkan/vulkan.hpp +++ b/vulkan/vulkan.hpp @@ -283,6 +283,20 @@ namespace VULKAN_HPP_NAMESPACE { } + template + ArrayProxy( T ( &ptr )[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + { + } + + template ::value, int>::type = 0> + ArrayProxy( typename std::remove_const::type ( &ptr )[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + { + } + # if __GNUC__ >= 9 # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Winit-list-lifetime" @@ -428,6 +442,26 @@ namespace VULKAN_HPP_NAMESPACE { } + template + ArrayProxyNoTemporaries( T ( &ptr )[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + { + } + + template + ArrayProxyNoTemporaries( T( &&ptr )[C] ) = delete; + + template ::value, int>::type = 0> + ArrayProxyNoTemporaries( typename std::remove_const::type ( &ptr )[C] ) VULKAN_HPP_NOEXCEPT + : m_count( C ) + , m_ptr( ptr ) + { + } + + template ::value, int>::type = 0> + ArrayProxyNoTemporaries( typename std::remove_const::type( &&ptr )[C] ) = delete; + ArrayProxyNoTemporaries( std::initializer_list const & list ) VULKAN_HPP_NOEXCEPT : m_count( static_cast( list.size() ) ) , m_ptr( list.begin() ) From 1bc663f851230d167f4915f484cefc14d7e4530d Mon Sep 17 00:00:00 2001 From: phantom10111 Date: Fri, 15 Apr 2022 17:38:23 +0200 Subject: [PATCH 2/2] Add tests for ArrayProxy constructors with raw arrays with size Add tests for new ArrayProxy and ArrayProxyNoTemporaries constructors. Also add more size assertions, to verify that ArrayProxy size is correct after construction. --- tests/ArrayProxy/ArrayProxy.cpp | 104 ++++++++++----- .../ArrayProxyNoTemporaries.cpp | 120 +++++++++++++----- 2 files changed, 158 insertions(+), 66 deletions(-) diff --git a/tests/ArrayProxy/ArrayProxy.cpp b/tests/ArrayProxy/ArrayProxy.cpp index 91c6944..1650d6f 100644 --- a/tests/ArrayProxy/ArrayProxy.cpp +++ b/tests/ArrayProxy/ArrayProxy.cpp @@ -52,6 +52,13 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct(i1); // not supported: cannot convert argument 1 from 'const int' to 'vk::ArrayProxy' fctc( i1 ); + vk::ArrayProxy ap1 = 1; + assert( ap1.size() == 1 ); + vk::ArrayProxy ap2 = i0; + assert( ap2.size() == 1 ); + vk::ArrayProxy ap3 = i1; + assert( ap3.size() == 1 ); + // count, T * int * i0p = &i0; fct( { 1, i0p } ); @@ -62,6 +69,26 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct({ 1, i1p }); // not supported: cannot convert argument 1 from 'initializer list' to 'vk::ArrayProxy' fctc( { 1, i1p } ); + vk::ArrayProxy ap4 = { 1, i0p }; + assert( ap4.size() == 1 ); + vk::ArrayProxy ap5 = { 1, i1p }; + assert( ap5.size() == 1 ); + + // T[count] + int ia0[2] = { 0, 1 }; + fct( ia0 ); + fctc( ia0 ); + + // const T[count] + const int ia1[2] = { 0, 1 }; + // fct( ia1 ); // not supported: cannot convert argument 1 from 'const int [2]' to 'vk::ArrayProxy' + fctc( ia1 ); + + vk::ArrayProxy ap6 = ia0; + assert( ap6.size() == 2 ); + vk::ArrayProxy ap7 = ia1; + assert( ap7.size() == 2 ); + // std::array std::array sa0 = { 0, 1 }; fct( sa0 ); @@ -80,20 +107,20 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct(sa3); // not supported: cannot convert argument 1 from 'const std::array' to 'vk::ArrayProxy' fctc( sa3 ); - vk::ArrayProxy ap2 = sa0; - assert( ap2.size() == 2 ); - // vk::ArrayProxy ap3 = sa1; // not supported: cannot convert from 'std::array' to 'vk::ArrayProxy' - // vk::ArrayProxy ap4 = sa2; // not supported: cannot convert from '_Ty *' to 'T *' - // vk::ArrayProxy ap5 = sa3; // not supported: cannot convert from 'const std::array' to 'vk::ArrayProxy' - - vk::ArrayProxy ap6 = sa0; - assert( ap6.size() == 2 ); - vk::ArrayProxy ap7 = sa1; - assert( ap7.size() == 2 ); - vk::ArrayProxy ap8 = sa2; + vk::ArrayProxy ap8 = sa0; assert( ap8.size() == 2 ); - vk::ArrayProxy ap9 = sa3; - assert( ap9.size() == 2 ); + // vk::ArrayProxy ap9 = sa1; // not supported: cannot convert from 'std::array' to 'vk::ArrayProxy' + // vk::ArrayProxy ap10 = sa2; // not supported: cannot convert from '_Ty *' to 'T *' + // vk::ArrayProxy ap11 = sa3; // not supported: cannot convert from 'const std::array' to 'vk::ArrayProxy' + + vk::ArrayProxy ap12 = sa0; + assert( ap12.size() == 2 ); + vk::ArrayProxy ap13 = sa1; + assert( ap13.size() == 2 ); + vk::ArrayProxy ap14 = sa2; + assert( ap14.size() == 2 ); + vk::ArrayProxy ap15 = sa3; + assert( ap15.size() == 2 ); // std::vector std::vector sv0 = { 0, 1 }; @@ -104,14 +131,14 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct(sv1); // not supported: cannot convert from 'const _Ty *' to 'T *' fctc( sv1 ); - vk::ArrayProxy ap10 = sv0; - assert( ap10.size() == 2 ); - // vk::ArrayProxy ap11 = sv1; // not supported: cannot convert from '_Ty *' to 'T *' + vk::ArrayProxy ap16 = sv0; + assert( ap16.size() == 2 ); + // vk::ArrayProxy ap17 = sv1; // not supported: cannot convert from '_Ty *' to 'T *' - vk::ArrayProxy ap12 = sv0; - assert( ap12.size() == 2 ); - vk::ArrayProxy ap13 = sv1; - assert( ap13.size() == 2 ); + vk::ArrayProxy ap18 = sv0; + assert( ap18.size() == 2 ); + vk::ArrayProxy ap19 = sv1; + assert( ap19.size() == 2 ); // std::initializer_list fct( {} ); @@ -145,19 +172,23 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct(il4); // not supported: cannot convert argument 1 from 'const std::initializer_list' to 'vk::ArrayProxy' fctc( il4 ); - // vk::ArrayProxy ap14 = il1; // not supported: cannot convert from 'const _Elem *' to 'T *' - // vk::ArrayProxy ap15 = il2; // not supported: cannot convert from 'std::initializer_list' to 'vk::ArrayProxy' - // vk::ArrayProxy ap16 = il3; // not supported: cannot convert from 'const _Elem *' to 'T *' - // vk::ArrayProxy ap17 = il4; // not supported: cannot convert from 'const std::initializer_list' to 'vk::ArrayProxy' + // vk::ArrayProxy ap20 = il1; // not supported: cannot convert from 'const _Elem *' to 'T *' + // vk::ArrayProxy ap21 = il2; // not supported: cannot convert from 'std::initializer_list' to 'vk::ArrayProxy' + // vk::ArrayProxy ap22 = il3; // not supported: cannot convert from 'const _Elem *' to 'T *' + // vk::ArrayProxy ap23 = il4; // not supported: cannot convert from 'const std::initializer_list' to 'vk::ArrayProxy' - vk::ArrayProxy ap18 = il1; - assert( ap18.size() == 2 ); - vk::ArrayProxy ap19 = il2; - assert( ap19.size() == 2 ); - vk::ArrayProxy ap20 = il3; - assert( ap20.size() == 2 ); - vk::ArrayProxy ap21 = il4; - assert( ap21.size() == 2 ); + vk::ArrayProxy ap24 = {}; + assert( ap24.size() == 0 ); + vk::ArrayProxy ap25 = { 0, 1 }; + assert( ap25.size() == 2 ); + vk::ArrayProxy ap26 = il1; + assert( ap26.size() == 2 ); + vk::ArrayProxy ap27 = il2; + assert( ap27.size() == 2 ); + vk::ArrayProxy ap28 = il3; + assert( ap28.size() == 2 ); + vk::ArrayProxy ap29 = il4; + assert( ap29.size() == 2 ); #if defined( VULKAN_HPP_SUPPORT_SPAN ) // std::span @@ -177,6 +208,15 @@ int main( int /*argc*/, char ** /*argv*/ ) std::span const ss3( sa3.begin(), sa3.end() ); // fct(ss3); // not supported: cannot convert from 'const std::span' to 'vk::ArrayProxy' fctc( ss3 ); + + vk::ArrayProxy ap30 = ss0; + assert( ap30.size() == 2 ); + vk::ArrayProxy ap31 = ss1; + assert( ap31.size() == 2 ); + vk::ArrayProxy ap32 = ss2; + assert( ap32.size() == 2 ); + vk::ArrayProxy ap33 = ss3; + assert( ap33.size() == 2 ); #endif } catch ( vk::SystemError const & err ) diff --git a/tests/ArrayProxyNoTemporaries/ArrayProxyNoTemporaries.cpp b/tests/ArrayProxyNoTemporaries/ArrayProxyNoTemporaries.cpp index 508af1f..5cd23c4 100644 --- a/tests/ArrayProxyNoTemporaries/ArrayProxyNoTemporaries.cpp +++ b/tests/ArrayProxyNoTemporaries/ArrayProxyNoTemporaries.cpp @@ -38,6 +38,18 @@ int getInt() return 1; } +int( &&getArrayReference() )[2] +{ + static int arr[2] = { 1, 2 }; + return std::move( arr ); +} + +int const( &&getConstArrayReference() )[2] +{ + static int const arr[2] = { 1, 2 }; + return std::move( arr ); +} + std::array getArray() { return { 1, 2 }; @@ -98,6 +110,13 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct(i1); // not supported: ArrayProxyNoTemporaries(const int &) fctc( i1 ); + // vk::ArrayProxyNoTemporaries ap1 = 1; // not supported: ArrayProxyNoTemporaries::ArrayProxyNoTemporaries(int &&) + + vk::ArrayProxyNoTemporaries ap2 = i0; + assert( ap2.size() == 1 ); + vk::ArrayProxyNoTemporaries ap3 = i1; + assert( ap3.size() == 1 ); + // count, T * int * i0p = &i0; fct( { 1, i0p } ); @@ -108,6 +127,32 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct({ 1, i1p }); // not supported: cannot convert argument 1 from 'initializer list' to 'vk::ArrayProxyNoTemporaries' fctc( { 1, i1p } ); + vk::ArrayProxyNoTemporaries ap4 = { 1, i0p }; + assert( ap4.size() == 1 ); + vk::ArrayProxyNoTemporaries ap5 = { 1, i1p }; + assert( ap5.size() == 1 ); + + // T[count] + int ia0[2] = { 0, 1 }; + fct( ia0 ); + fctc( ia0 ); + + // const T[count] + const int ia1[2] = { 0, 1 }; + // fct( ia1 ); // not supported: cannot convert argument 1 from 'const int [2]' to 'vk::ArrayProxyNoTemporaries' + fctc( ia1 ); + + vk::ArrayProxyNoTemporaries ap6 = ia0; + assert( ap6.size() == 2 ); + vk::ArrayProxyNoTemporaries ap7 = ia1; + assert( ap7.size() == 2 ); + + // getArrayReference + // fct( getConstArrayReference() ); // not supported + // fctc( getConstArrayReference() ); // not supported + // fct( getArrayReference() ); // not supported + // fctc( getArrayReference() ); // not supported + // std::array std::array sa0 = { 0, 1 }; fct( sa0 ); @@ -135,21 +180,22 @@ int main( int /*argc*/, char ** /*argv*/ ) // fctc( getArray() ); // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries>(V &&) // from std::array constructors - vk::ArrayProxyNoTemporaries ap2 = sa0; - assert( ap2.size() == 2 ); - // vk::ArrayProxyNoTemporaries ap3 = sa1; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries&>(V) vk::ArrayProxyNoTemporaries ap4 = sa2; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries&>(V) vk::ArrayProxyNoTemporaries ap5 = sa3; // not supported: attempting to reference a deleted function: + vk::ArrayProxyNoTemporaries ap8 = sa0; + assert( ap8.size() == 2 ); + + // vk::ArrayProxyNoTemporaries ap9 = sa1; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries&>(V) vk::ArrayProxyNoTemporaries ap10 = sa2; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries&>(V) vk::ArrayProxyNoTemporaries ap11 = sa3; // not supported: attempting to reference a deleted function: // ArrayProxyNoTemporaries&>(V) - vk::ArrayProxyNoTemporaries ap6 = sa0; - assert( ap6.size() == 2 ); - vk::ArrayProxyNoTemporaries ap7 = sa1; - assert( ap7.size() == 2 ); - vk::ArrayProxyNoTemporaries ap8 = sa2; - assert( ap8.size() == 2 ); - vk::ArrayProxyNoTemporaries ap9 = sa3; - assert( ap9.size() == 2 ); + vk::ArrayProxyNoTemporaries ap12 = sa0; + assert( ap12.size() == 2 ); + vk::ArrayProxyNoTemporaries ap13 = sa1; + assert( ap13.size() == 2 ); + vk::ArrayProxyNoTemporaries ap14 = sa2; + assert( ap14.size() == 2 ); + vk::ArrayProxyNoTemporaries ap15 = sa3; + assert( ap15.size() == 2 ); // std::vector std::vector sv0 = { 0, 1 }; @@ -161,11 +207,6 @@ int main( int /*argc*/, char ** /*argv*/ ) // fct(sv1); // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries>&>(V) fctc( sv1 ); - vk::ArrayProxyNoTemporaries ap10 = sv0; - assert( ap10.size() == 2 ); - // vk::ArrayProxyNoTemporaries ap11 = sv1; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries>&>(V) - // getVector // fct( getConstVector() ); // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries>>(V &&) fctc( getConstVector() ); // not supported: attempting to reference a deleted function: @@ -173,10 +214,16 @@ int main( int /*argc*/, char ** /*argv*/ ) // function: ArrayProxyNoTemporaries>>(V &&) fctc( getVector() ); // not supported: attempting to reference a // deleted function: ArrayProxyNoTemporaries>>(V &&) - vk::ArrayProxyNoTemporaries ap12 = sv0; - assert( ap12.size() == 2 ); - vk::ArrayProxyNoTemporaries ap13 = sv1; - assert( ap13.size() == 2 ); + vk::ArrayProxyNoTemporaries ap16 = sv0; + assert( ap16.size() == 2 ); + + // vk::ArrayProxyNoTemporaries ap17 = sv1; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries>&>(V) + + vk::ArrayProxyNoTemporaries ap18 = sv0; + assert( ap18.size() == 2 ); + vk::ArrayProxyNoTemporaries ap19 = sv1; + assert( ap19.size() == 2 ); // std::initializer_list fct( {} ); @@ -217,20 +264,25 @@ int main( int /*argc*/, char ** /*argv*/ ) // deleted function: ArrayProxyNoTemporaries(std::initializer_list &&) fctc( getInitializerList() ); // not supported: attempting to reference // a deleted function: ArrayProxyNoTemporaries(std::initializer_list &&) - // vk::ArrayProxyNoTemporaries ap14 = il1; // not supported: cannot convert from 'const int *' to 'int *' - // vk::ArrayProxyNoTemporaries ap15 = il2; // not supported: attempting to reference a deleted function: - // ArrayProxyNoTemporaries&>(V) vk::ArrayProxyNoTemporaries ap16 = il3; // not supported: cannot convert from 'const int *' - // to 'int *' vk::ArrayProxyNoTemporaries ap17 = il4; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries ap20 = il1; // not supported: cannot convert from 'const int *' to 'int *' + // vk::ArrayProxyNoTemporaries ap21 = il2; // not supported: attempting to reference a deleted function: + // ArrayProxyNoTemporaries&>(V) vk::ArrayProxyNoTemporaries ap22 = il3; // not supported: cannot convert from 'const int *' + // to 'int *' vk::ArrayProxyNoTemporaries ap23 = il4; // not supported: attempting to reference a deleted function: ArrayProxyNoTemporaries&>(V) - vk::ArrayProxyNoTemporaries ap18 = il1; - assert( ap18.size() == 2 ); - vk::ArrayProxyNoTemporaries ap19 = il2; - assert( ap19.size() == 2 ); - vk::ArrayProxyNoTemporaries ap20 = il3; - assert( ap20.size() == 2 ); - vk::ArrayProxyNoTemporaries ap21 = il4; - assert( ap21.size() == 2 ); + vk::ArrayProxyNoTemporaries ap24 = {}; + assert( ap24.size() == 0 ); + + //vk::ArrayProxyNoTemporaries ap25 = { 0, 1 }; // not supported + + vk::ArrayProxyNoTemporaries ap26 = il1; + assert( ap26.size() == 2 ); + vk::ArrayProxyNoTemporaries ap27 = il2; + assert( ap27.size() == 2 ); + vk::ArrayProxyNoTemporaries ap28 = il3; + assert( ap28.size() == 2 ); + vk::ArrayProxyNoTemporaries ap29 = il4; + assert( ap29.size() == 2 ); } catch ( vk::SystemError const & err ) {