diff --git a/include/llama/Accessors.hpp b/include/llama/Accessors.hpp index 2a30a9f2d4..34b6445639 100644 --- a/include/llama/Accessors.hpp +++ b/include/llama/Accessors.hpp @@ -1,6 +1,7 @@ #pragma once #include "Concepts.hpp" +#include "ProxyRefOpMixin.hpp" #include "macros.hpp" #include @@ -34,11 +35,40 @@ namespace llama::accessor /// Allows only read access by qualifying the references to memory with const. Only works on l-value references. struct Const { + // for l-value references template LLAMA_FN_HOST_ACC_INLINE auto operator()(T& r) const -> const T& { return r; } + + template + struct Reference : ProxyRefOpMixin, typename Ref::value_type> + { + using value_type = typename Ref::value_type; + + Ref ref; + + // NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) + operator value_type() const + { + return static_cast(ref); + } + + template + auto operator=(T) -> Reference& + { + static_assert(sizeof(T) == 0, "You cannot write through a Const accessor"); + return *this; + } + }; + + // for proxy references + template, int> = 0> + LLAMA_FN_HOST_ACC_INLINE auto operator()(ProxyReference r) const + { + return Reference{{}, std::move(r)}; + } }; /// Qualifies references to memory with __restrict. Only works on l-value references. diff --git a/tests/accessor.cpp b/tests/accessor.cpp index fc26a4d1b0..3935193f67 100644 --- a/tests/accessor.cpp +++ b/tests/accessor.cpp @@ -76,6 +76,25 @@ TEMPLATE_TEST_CASE( iotaCheckView(view); } +TEST_CASE("view.withAccessor.shallowCopy.Const") +{ + auto view + = llama::allocView(llama::mapping::AoS{llama::ArrayExtents{4, 4}, Vec3I{}}, llama::bloballoc::SharedPtr{}); + iotaFillView(view); + auto view2 = llama::withAccessor(llama::shallowCopy(view)); + iotaCheckView(view2); +} + +TEST_CASE("view.withAccessor.shallowCopy.Const.ProxyRef") +{ + auto view = llama::allocView( + llama::mapping::Byteswap, Vec3I, llama::mapping::BindAoS<>::fn>{{}}, + llama::bloballoc::SharedPtr{}); + iotaFillView(view); + auto view2 = llama::withAccessor(llama::shallowCopy(view)); + iotaCheckView(view2); +} + #ifdef __cpp_lib_atomic_ref TEMPLATE_TEST_CASE( "view.withAccessor.shallowCopy.Atomic",