diff --git a/include/vectorwrapper/forward_wrapper.hpp b/include/vectorwrapper/forward_wrapper.hpp new file mode 100644 index 0000000..e30acab --- /dev/null +++ b/include/vectorwrapper/forward_wrapper.hpp @@ -0,0 +1,45 @@ +/* + * Copyright 2015-2018 Michele "King_DuckZ" Santullo + * + * 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. + */ + +#pragma once + +#if defined VWR_OUTER_NAMESPACE +namespace VWR_OUTER_NAMESPACE { +#endif + +namespace vwr { + template + class forward_wrapper { + public: + forward_wrapper() { new(&m_storage) V; } + forward_wrapper (const forward_wrapper&) = delete; + forward_wrapper (forward_wrapper&&) = delete; + ~forward_wrapper() { vector().~V(); } + + forward_wrapper& operator= (const forward_wrapper&) = delete; + forward_wrapper& operator= (forward_wrapper&&) = delete; + + private: + V& vector() { return *reinterpret_cast(&m_storage); } + //const V& vector() const { return *reinterpret_cast(&m_storage); } + + Storage m_storage; + }; +} //namespace vwr + +#if defined VWR_OUTER_NAMESPACE +} //namespace VWR_OUTER_NAMESPACE +#endif diff --git a/include/vectorwrapper/implem_vec_base.hpp b/include/vectorwrapper/implem_vec_base.hpp index 803c295..4ea4cd7 100644 --- a/include/vectorwrapper/implem_vec_base.hpp +++ b/include/vectorwrapper/implem_vec_base.hpp @@ -60,6 +60,8 @@ namespace vwr { friend Vec& assign_same_type ( Vec& parLeft, const Vec& parRight ); public: typedef V vector_type; + typedef typename get_storage_type::type storage_type; + typedef typename VectorWrapperInfo::scalar_type scalar_type; enum { @@ -77,8 +79,8 @@ namespace vwr { scalar_type& operator[] ( size_type parIndex ); const scalar_type& operator[] ( size_type parIndex ) const; - vector_type& data ( void ) { return m_wrapped; } - const vector_type& data ( void ) const { return m_wrapped; } + storage_type& data ( void ) { return m_wrapped; } + const storage_type& data ( void ) const { return m_wrapped; } template const typename std::enable_if::value and directly_convertible::value, V2>::type& cast ( void ) const; @@ -107,7 +109,7 @@ namespace vwr { template void assign_values_op_scalar (Op parOp, const bt::number_seq& parSeq, const scalar_type& parOther); - vector_type m_wrapped; + storage_type m_wrapped; }; template < diff --git a/include/vectorwrapper/implem_vec_base.inl b/include/vectorwrapper/implem_vec_base.inl index 8711405..5bdbe0c 100644 --- a/include/vectorwrapper/implem_vec_base.inl +++ b/include/vectorwrapper/implem_vec_base.inl @@ -78,7 +78,7 @@ namespace vwr { template auto VecBase::operator[] (size_type parIndex) const -> const scalar_type& { - return VecGetter::get_at(const_cast(m_wrapped), parIndex); + return VecGetter::get_at(const_cast(m_wrapped), parIndex); } template diff --git a/include/vectorwrapper/implem_vec_common.hpp b/include/vectorwrapper/implem_vec_common.hpp index 6b8452f..210a7cc 100644 --- a/include/vectorwrapper/implem_vec_common.hpp +++ b/include/vectorwrapper/implem_vec_common.hpp @@ -34,30 +34,41 @@ namespace vwr { namespace implem { define_has_typedef(lower_vector_type, LowerVec); define_has_typedef(higher_vector_type, HigherVec); + define_has_typedef(storage_type, StorageType); define_has_enum(offset_x, OffsetX); define_has_method(get_at, GetAt); define_has_enum(cast_ignore_trailing_properties, CastIgnoreTrailingProperties); + template >::value> struct get_storage_type; + template struct get_storage_type { + typedef typename VectorWrapperInfo::storage_type type; + static_assert(alignof(type) >= alignof(V), "Requested storage type's alignment is not compatible with vector_type"); + }; + template struct get_storage_type { + typedef V type; + }; + template >::value and std::is_standard_layout::value> struct VecGetter; template struct VecGetter { - static typename VectorWrapperInfo::scalar_type& get_at ( T& parVec, size_type parIndex ); + typedef typename get_storage_type::type storage_type; + static typename VectorWrapperInfo::scalar_type& get_at ( storage_type& parVec, size_type parIndex ); }; template struct VecGetter { + typedef typename get_storage_type::type storage_type; private: static_assert(HasGetAtMethod>::value, "You must provide a get_at() static method for this vector_type"); typedef typename VectorWrapperInfo::scalar_type scalar_type; - typedef T vector_type; - using get_at_func = decltype(&VectorWrapperInfo::get_at)(size_type, vector_type&); + using get_at_func = decltype(&VectorWrapperInfo::get_at)(size_type, storage_type&); using get_at_rettype = typename std::result_of::type; static_assert(not std::is_rvalue_reference::value, "rvalue ref return types not implemented"); static_assert(std::is_lvalue_reference::value, "Read-only vectors not implemented"); public: - static get_at_rettype get_at ( T& parVec, size_type parIndex ); + static get_at_rettype get_at ( storage_type& parVec, size_type parIndex ); }; template struct get_offset_enum_from_index; diff --git a/include/vectorwrapper/vectorwrapper.inl b/include/vectorwrapper/vectorwrapper.inl index e0d3f8b..9250f29 100644 --- a/include/vectorwrapper/vectorwrapper.inl +++ b/include/vectorwrapper/vectorwrapper.inl @@ -21,7 +21,7 @@ namespace VWR_OUTER_NAMESPACE { namespace vwr { namespace implem { template - typename VectorWrapperInfo::scalar_type& VecGetter::get_at (T& parVec, size_type parIndex) { + typename VectorWrapperInfo::scalar_type& VecGetter::get_at (storage_type& parVec, size_type parIndex) { assert(parIndex < VectorWrapperInfo::dimensions); typedef T vector_type; typedef typename VectorWrapperInfo::scalar_type scalar_type; @@ -31,7 +31,7 @@ namespace vwr { } template - auto VecGetter::get_at (T& parVec, size_type parIndex) -> get_at_rettype { + auto VecGetter::get_at (storage_type& parVec, size_type parIndex) -> get_at_rettype { assert(parIndex < VectorWrapperInfo::dimensions); return VectorWrapperInfo::get_at(parIndex, parVec); } diff --git a/test/unit/CMakeLists.txt b/test/unit/CMakeLists.txt index 5d0ed76..829438e 100644 --- a/test/unit/CMakeLists.txt +++ b/test/unit/CMakeLists.txt @@ -10,6 +10,7 @@ add_executable(${PROJECT_NAME} test_sequence_range.cpp test_offset_getters.cpp test_custom_type.cpp + test_custom_storage.cpp ) target_link_libraries(${PROJECT_NAME} diff --git a/test/unit/test_custom_storage.cpp b/test/unit/test_custom_storage.cpp new file mode 100644 index 0000000..ef30100 --- /dev/null +++ b/test/unit/test_custom_storage.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2015-2017 Michele "King_DuckZ" Santullo + * + * 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. + */ + +#include "vectorwrapper/vectorwrapper.hpp" +#include "vectorwrapper/forward_wrapper.hpp" +#include + +namespace { + struct VecType { + int a, b, c; + }; +} //unnamed namespace + +namespace vwr { + template <> + struct VectorWrapperInfo { + enum { dimensions = 3}; + typedef int scalar_type; + typedef int storage_type[3]; + enum { + offset_x = offsetof(VecType, a), + offset_y = offsetof(VecType, b), + offset_z = offsetof(VecType, c) + }; + }; +} //namespace vwr + +namespace { + typedef vwr::Vec ivec3; +} //unnamed namespace + +TEST(vwr, custom_storage_type) { + ivec3 v(55); + + EXPECT_EQ(v.x(), 55); + EXPECT_EQ(v.y(), 55); + EXPECT_EQ(v.z(), 55); + + auto& data = v.data(); +} diff --git a/testme.cpp b/testme.cpp new file mode 100644 index 0000000..673feea --- /dev/null +++ b/testme.cpp @@ -0,0 +1,41 @@ +#include + +template +int get_at (const T&, int); + +struct XY { + int x, y; +}; + +template <> int get_at(const int(&in)[2], int i) { return in[i]; } +template <> int get_at(const XY& in, int i) { return (i ? in.y : in.x); } + +template +struct Vec { + int x() const { return get_at(m_storage_type, 0); } + int y() const { return get_at(m_storage_type, 1); } + + T m_storage_type; +}; + +template +std::ostream& operator<< (std::ostream& os, const Vec& v) { + os << '<' << v.x() << ',' << v.y() << '>'; + return os; +} + +int main() { + Vec v1; + Vec v2; + + v1.m_storage_type[0] = 1234; + v1.m_storage_type[1] = 7777; + + v2.m_storage_type.x = 44; + v2.m_storage_type.y = 9999; + + std::cout << v1 << '\n'; + std::cout << v2 << '\n'; + + return 0; +}