diff --git a/core/src/View/Kokkos_ViewCtor.hpp b/core/src/View/Kokkos_ViewCtor.hpp index e40d62220e9..7839fda5516 100644 --- a/core/src/View/Kokkos_ViewCtor.hpp +++ b/core/src/View/Kokkos_ViewCtor.hpp @@ -81,7 +81,7 @@ struct ViewCtorProp> { KOKKOS_FUNCTION ViewCtorProp(const type &arg) : value(arg) {} KOKKOS_FUNCTION - ViewCtorProp(type &&arg) : value(std::move(arg)) {} + ViewCtorProp(type &&arg) : value(arg) {} type value; }; @@ -212,12 +212,16 @@ struct ViewCtorProp : public ViewCtorProp... { using memory_space = typename var_memory_space::type; using execution_space = typename var_execution_space::type; using pointer_type = typename var_pointer::type; - - //! Construct from a matching argument list. + + // Construct from a matching argument list. + // + // Note that if P is empty, this constructor is the default constructor. + // On the other hand, if P is not empty, the constraint ensures that + // the default constructor cannot be called. template >::type>...>>> - explicit ViewCtorProp(Args&&...args) + std::is_constructible, Args &&>...>>> + ViewCtorProp(Args &&...args) : ViewCtorProp(std::forward(args))... {} template @@ -237,9 +241,11 @@ struct ViewCtorProp : public ViewCtorProp... { template ViewCtorProp(view_ctor_prop_args const &arg) : view_ctor_prop_base( - static_cast const &>(arg))... {} - - //ViewCtorProp(view_ctor_prop_args<> const &) {} + static_cast const &>(arg))... { + // Suppress an unused argument warning that (at least at one point) would + // show up if sizeof...(Args) == 0 + (void)arg; + } }; #if !defined(KOKKOS_COMPILER_MSVC) || !defined(KOKKOS_COMPILER_NVCC) @@ -453,9 +459,9 @@ inline constexpr Kokkos::Impl::AllowPadding_t AllowPadding{}; * alignment */ template -auto view_alloc(Args&&...args) { - using return_type = - Impl::ViewCtorProp>::type...>; +auto view_alloc(Args &&...args) { + using return_type = Impl::ViewCtorProp>::type...>; static_assert(!return_type::has_pointer, "Cannot give pointer-to-memory for view allocation"); diff --git a/core/unit_test/TestViewCtorProp.hpp b/core/unit_test/TestViewCtorProp.hpp index f3d9e93d4f0..0871e4b798a 100644 --- a/core/unit_test/TestViewCtorProp.hpp +++ b/core/unit_test/TestViewCtorProp.hpp @@ -18,7 +18,7 @@ #include -namespace Test { +namespace { // Check Kokkos::Impl::is_view_label. TEST(TEST_CATEGORY, is_view_label) { @@ -28,17 +28,29 @@ TEST(TEST_CATEGORY, is_view_label) { static_assert(Kokkos::Impl::is_view_label::value); static_assert(Kokkos::Impl::is_view_label::value); + // A char* is not a label. Thus, a label is distinguished from a pointer type. static_assert(!Kokkos::Impl::is_view_label::value); } -// Check traits of Kokkos::Impl::ViewCtorProp. +// Check traits of Kokkos::Impl::ViewCtorProp<>. +TEST(TEST_CATEGORY, vcp_empty_traits) { + using vcp_empty_t = Kokkos::Impl::ViewCtorProp<>; + + // Check that the empty view constructor properties class is default + // constructible. This is needed for calls of Kokkos::view_alloc(). + static_assert(std::is_default_constructible_v); + + static_assert(std::is_same_v); +} + +// Check traits of base class Kokkos::Impl::ViewCtorProp. TEST(TEST_CATEGORY, vcp_label_base_traits) { using vcp_label_base_t = Kokkos::Impl::ViewCtorProp; static_assert(std::is_same_v); // Check that the base class is default constructible. The default constructor - // may be called by the copy constructor of the derived class, such as when + // may be called by the copy constructor of deriveded classes, such as when // copy constructing a view constructor properties object from another view // constructor properties object that holds fewer properties. static_assert(std::is_default_constructible_v); @@ -54,7 +66,7 @@ TEST(TEST_CATEGORY, vcp_label_base_traits) { static_assert(std::is_constructible_v); } -// Check traits of Kokkos::Impl::ViewCtorProp. +// Check traits of derived class Kokkos::Impl::ViewCtorProp. TEST(TEST_CATEGORY, vcp_label_traits) { using vcp_label_base_t = Kokkos::Impl::ViewCtorProp; using vcp_label_t = Kokkos::Impl::ViewCtorProp; @@ -75,10 +87,7 @@ TEST(TEST_CATEGORY, vcp_label_traits) { static_assert(std::is_constructible_v); static_assert(std::is_constructible_v); - // Kokkos::Impl::ViewCtorProp cannot be constructed from - // a `char*` because `char*` does not satisfy `Kokkos::Impl::is_view_label`, - // hence the constructor cannot access the type alias `type`. - static_assert(!std::is_constructible_v); + static_assert(std::is_constructible_v); } // Check that the constructor of Kokkos::Impl::ViewCtorProp @@ -106,4 +115,31 @@ TEST(TEST_CATEGORY, vcp_label_view_alloc_can_move) { "our label"); } -} // namespace Test +// Check the copy constructor of Kokkos::Impl::ViewCtorProp. +TEST(TEST_CATEGORY, vcp_label_copy_constructor) { + using vcp_empty_t = Kokkos::Impl::ViewCtorProp<>; + using vcp_label_t = Kokkos::Impl::ViewCtorProp; + + // Copy construction from an empty view constructor properties object. + static_assert(std::is_constructible_v); + + vcp_empty_t prop_empty; + vcp_label_t prop_empty_copy(prop_empty); + + ASSERT_TRUE( + Kokkos::Impl::get_property(prop_empty_copy) + .empty()); + + // Copy construction from a view constructor properties object with a label. + static_assert(std::is_copy_constructible_v); + + auto prop = Kokkos::view_alloc("our label"); + vcp_label_t prop_copy(prop); + + ASSERT_EQ(Kokkos::Impl::get_property(prop), + "our label"); + ASSERT_EQ(Kokkos::Impl::get_property(prop_copy), + "our label"); +} + +} // namespace