diff --git a/doc/array.xml b/doc/array.xml index 68ee5a3..ecb95ef 100644 --- a/doc/array.xml +++ b/doc/array.xml @@ -81,7 +81,8 @@ Update: std::array is (as of C++11) part of the C++ standard. The differences between boost::array and std::array are minimal. - If you are using C++11, you should consider using std::array instead of boost::array. + If you are using C++11, you should consider using std::array instead of boost::array, + unless you're interested in constexpr usage of boost::array. Currently (2015 year) std::array misses constexpr. Class array fulfills most @@ -117,7 +118,8 @@ - STL compliant container wrapper for arrays of constant size + STL compliant container wrapper for arrays of constant size. + Provides extended constexpr support on C++14 compatible compilers (marked with cxx14_constexpr). T @@ -163,41 +165,38 @@ - - iterator + + cxx14_constexpr iterator - - const_iterator + + constexpr const_iterator iterator for the first element - will not throw - - iterator + + cxx14_constexpr iterator - - const_iterator + + constexpr const_iterator iterator for position after the last element - will not throw - + - const_iterator + constexpr const_iterator constant iterator for the first element - will not throw - + - const_iterator + constexpr const_iterator constant iterator for position after the last element @@ -207,10 +206,10 @@ - + reverse_iterator - + const_reverse_iterator @@ -218,17 +217,17 @@ - + reverse_iterator - + const_reverse_iterator reverse iterator for position after the last element in reverse iteration - + const_reverse_iterator @@ -237,23 +236,23 @@ will not throw - + const_reverse_iterator constant reverse iterator for position after the last element in reverse iteration - will not throw - size_type + constexpr size_type N + will not throw - bool + constexpr bool N==0 will not throw @@ -267,14 +266,14 @@ - reference + cxx14_constexpr reference size_type - const_reference + cxx14_constexpr const_reference size_type @@ -287,14 +286,14 @@ - reference + cxx14_constexpr reference size_type - const_reference + cxx14_constexpr const_reference size_type @@ -305,23 +304,22 @@ - - reference + + cxx14_constexpr reference - - const_reference + + constexpr const_reference N > 0 the first element - will not throw - - reference + + cxx14_constexpr reference - - const_reference + + constexpr const_reference N > 0 the last element @@ -329,13 +327,13 @@ - const T* + constexpr const T* elems will not throw - T* + constexpr T* elems will not throw @@ -523,7 +521,7 @@ - T + cxx14_constexpr T array<T, N>& @@ -543,7 +541,7 @@ - T + cxx14_constexpr T const array<T, N>& diff --git a/include/boost/array.hpp b/include/boost/array.hpp index 3ac0ffc..c8fca9f 100644 --- a/include/boost/array.hpp +++ b/include/boost/array.hpp @@ -13,6 +13,7 @@ * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * + * 4 Aug 2015 - Added more constexpr and noexcept (Antony Polukhin) * 9 Jan 2013 - (mtc) Added constexpr * 14 Apr 2012 - (mtc) Added support for boost::hash * 28 Dec 2010 - (mtc) Added cbegin and cend (and crbegin and crend) for C++Ox compatibility. @@ -73,13 +74,13 @@ namespace boost { typedef std::ptrdiff_t difference_type; // iterator support - iterator begin() { return elems; } - const_iterator begin() const { return elems; } - const_iterator cbegin() const { return elems; } + BOOST_CXX14_CONSTEXPR iterator begin() BOOST_NOEXCEPT { return elems; } + BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return elems; } + BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return elems; } - iterator end() { return elems+N; } - const_iterator end() const { return elems+N; } - const_iterator cend() const { return elems+N; } + BOOST_CXX14_CONSTEXPR iterator end() BOOST_NOEXCEPT { return elems+N; } + BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return elems+N; } + BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return elems+N; } // reverse iterator support #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) @@ -96,62 +97,67 @@ namespace boost { typedef std::reverse_iterator const_reverse_iterator; #endif - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { + reverse_iterator rbegin() BOOST_NOEXCEPT { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } - const_reverse_iterator crbegin() const { + const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { + reverse_iterator rend() BOOST_NOEXCEPT { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } - const_reverse_iterator crend() const { + const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } // operator[] - reference operator[](size_type i) - { - return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i]; + BOOST_CXX14_CONSTEXPR reference operator[](size_type i) { + BOOST_ASSERT_MSG( i < N, "out of range" ); + return elems[i]; } - - /*BOOST_CONSTEXPR*/ const_reference operator[](size_type i) const - { - return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i]; + BOOST_CXX14_CONSTEXPR const_reference operator[](size_type i) const { + BOOST_ASSERT_MSG( i < N, "out of range" ); + return elems[i]; } // at() with range check - reference at(size_type i) { return rangecheck(i), elems[i]; } - /*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; } + BOOST_CXX14_CONSTEXPR reference at(size_type i) { + rangecheck(i); + return elems[i]; + } + BOOST_CXX14_CONSTEXPR const_reference at(size_type i) const { + rangecheck(i); + return elems[i]; + } // front() and back() - reference front() - { + BOOST_CXX14_CONSTEXPR reference front() BOOST_NOEXCEPT { return elems[0]; } - BOOST_CONSTEXPR const_reference front() const - { + BOOST_CONSTEXPR const_reference front() const BOOST_NOEXCEPT { return elems[0]; } - - reference back() - { + + BOOST_CXX14_CONSTEXPR reference back() BOOST_NOEXCEPT { return elems[N-1]; } - BOOST_CONSTEXPR const_reference back() const - { + BOOST_CONSTEXPR const_reference back() const BOOST_NOEXCEPT { return elems[N-1]; } // size is constant - static BOOST_CONSTEXPR size_type size() { return N; } - static BOOST_CONSTEXPR bool empty() { return false; } - static BOOST_CONSTEXPR size_type max_size() { return N; } + static BOOST_CONSTEXPR size_type size() BOOST_NOEXCEPT { return N; } + static BOOST_CONSTEXPR bool empty() BOOST_NOEXCEPT { return false; } + static BOOST_CONSTEXPR size_type max_size() BOOST_NOEXCEPT { return N; } enum { static_size = N }; // swap (note: linear complexity) @@ -160,12 +166,12 @@ namespace boost { boost::swap(elems[i],y.elems[i]); } - // direct access to data (read-only) - const T* data() const { return elems; } - T* data() { return elems; } + // direct access to data + BOOST_CXX14_CONSTEXPR T* data() BOOST_NOEXCEPT { return elems; } + BOOST_CONSTEXPR const T* data() const BOOST_NOEXCEPT { return elems; } // use array as C array (direct read/write access to data) - T* c_array() { return elems; } + BOOST_CXX14_CONSTEXPR T* c_array() BOOST_NOEXCEPT { return elems; } // assignment with type conversion template @@ -176,8 +182,7 @@ namespace boost { // assign one value to all elements void assign (const T& value) { fill ( value ); } // A synonym for fill - void fill (const T& value) - { + void fill (const T& value) { std::fill_n(begin(),size(),value); } @@ -190,7 +195,6 @@ namespace boost { template< class T > class array< T, 0 > { - public: // type definitions typedef T value_type; @@ -202,13 +206,13 @@ namespace boost { typedef std::ptrdiff_t difference_type; // iterator support - iterator begin() { return iterator( reinterpret_cast< T * >( this ) ); } - const_iterator begin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); } - const_iterator cbegin() const { return const_iterator( reinterpret_cast< const T * >( this ) ); } + iterator begin() BOOST_NOEXCEPT { return iterator( reinterpret_cast< T * >( this ) ); } + const_iterator begin() const BOOST_NOEXCEPT { return const_iterator( reinterpret_cast< const T * >( this ) ); } + const_iterator cbegin() const BOOST_NOEXCEPT { return const_iterator( reinterpret_cast< const T * >( this ) ); } - iterator end() { return begin(); } - const_iterator end() const { return begin(); } - const_iterator cend() const { return cbegin(); } + iterator end() BOOST_NOEXCEPT { return begin(); } + const_iterator end() const BOOST_NOEXCEPT { return begin(); } + const_iterator cend() const BOOST_NOEXCEPT { return cbegin(); } // reverse iterator support #if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) @@ -225,30 +229,30 @@ namespace boost { typedef std::reverse_iterator const_reverse_iterator; #endif - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { + reverse_iterator rbegin() BOOST_NOEXCEPT { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } - const_reverse_iterator crbegin() const { + const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { + reverse_iterator rend() BOOST_NOEXCEPT { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } - const_reverse_iterator crend() const { + const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator(begin()); } // operator[] - reference operator[](size_type /*i*/) - { + reference operator[](size_type /*i*/) { return failed_rangecheck(); } - /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const - { + /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const { return failed_rangecheck(); } @@ -257,41 +261,37 @@ namespace boost { /*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const { return failed_rangecheck(); } // front() and back() - reference front() - { + reference front() { return failed_rangecheck(); } - BOOST_CONSTEXPR const_reference front() const - { + BOOST_CONSTEXPR const_reference front() const { return failed_rangecheck(); } - reference back() - { + reference back() { return failed_rangecheck(); } - BOOST_CONSTEXPR const_reference back() const - { + BOOST_CONSTEXPR const_reference back() const { return failed_rangecheck(); } // size is constant - static BOOST_CONSTEXPR size_type size() { return 0; } - static BOOST_CONSTEXPR bool empty() { return true; } - static BOOST_CONSTEXPR size_type max_size() { return 0; } + static BOOST_CONSTEXPR size_type size() BOOST_NOEXCEPT { return 0; } + static BOOST_CONSTEXPR bool empty() BOOST_NOEXCEPT { return true; } + static BOOST_CONSTEXPR size_type max_size() BOOST_NOEXCEPT { return 0; } enum { static_size = 0 }; void swap (array& /*y*/) { } - // direct access to data (read-only) - const T* data() const { return 0; } - T* data() { return 0; } + // direct access to data + BOOST_CXX14_CONSTEXPR T* data() BOOST_NOEXCEPT { return 0; } + BOOST_CONSTEXPR const T* data() const BOOST_NOEXCEPT { return 0; } // use array as C array (direct read/write access to data) - T* c_array() { return 0; } + BOOST_CXX14_CONSTEXPR T* c_array() { return 0; } // assignment with type conversion template @@ -300,8 +300,8 @@ namespace boost { } // assign one value to all elements - void assign (const T& value) { fill ( value ); } - void fill (const T& ) {} + BOOST_CXX14_CONSTEXPR void assign (const T& value) { fill ( value ); } + BOOST_CXX14_CONSTEXPR void fill (const T& ) {} // check range (may be private because it is static) static reference failed_rangecheck () { @@ -380,14 +380,14 @@ namespace boost { #else // Specific for boost::array: simply returns its elems data member. template - T(&get_c_array(boost::array& arg))[N] + BOOST_CXX14_CONSTEXPR T(&get_c_array(boost::array& arg) BOOST_NOEXCEPT)[N] { return arg.elems; } // Const version. template - const T(&get_c_array(const boost::array& arg))[N] + BOOST_CXX14_CONSTEXPR const T(&get_c_array(const boost::array& arg) BOOST_NOEXCEPT)[N] { return arg.elems; } @@ -420,13 +420,13 @@ namespace boost { } template - T &get(boost::array &arr) BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR T &get(boost::array &arr) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(boost::array &) index out of range" ); return arr[Idx]; } template - const T &get(const boost::array &arr) BOOST_NOEXCEPT { + BOOST_CXX14_CONSTEXPR const T &get(const boost::array &arr) BOOST_NOEXCEPT { BOOST_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" ); return arr[Idx]; } @@ -451,7 +451,7 @@ namespace std { #endif #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) -# pragma warning(pop) +# pragma warning(pop) #endif #endif /*BOOST_ARRAY_HPP*/ diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1a04d91..9181eac 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -18,7 +18,7 @@ test-suite array : [ run array5.cpp ] [ run array6.cpp unit_test_framework : : : : array6 ] [ run array7.cpp unit_test_framework : : : : array7 ] -# [ run array_constexpr.cpp unit_test_framework : : : : array_constexpr ] + [ run array_constexpr.cpp unit_test_framework : : : : array_constexpr ] [ compile-fail array_getfail1.cpp ] [ compile-fail array_getfail2.cpp ] [ run array_hash.cpp unit_test_framework : : : : array_hash ] diff --git a/test/array_constexpr.cpp b/test/array_constexpr.cpp index 927bdec..eda8283 100644 --- a/test/array_constexpr.cpp +++ b/test/array_constexpr.cpp @@ -1,4 +1,5 @@ /* tests using constexpr on boost:array + * (C) Copyright Antony Polukhin 2015 * (C) Copyright Marshall Clow 2012 * Distributed under the Boost Software License, Version 1.0. (See * accompanying file LICENSE_1_0.txt or copy at @@ -9,16 +10,12 @@ #include #include #include -#ifndef BOOST_NO_CXX11_HDR_ARRAY -#include -#endif #define BOOST_TEST_MAIN #include #ifndef BOOST_NO_CXX11_CONSTEXPR constexpr boost::array arr {{ 0,1,2,3,4,5,6,7,8,9 }}; -constexpr std::array arr_std {{ 0,1,2,3,4,5,6,7,8,9 }}; template void sink ( T t ) {} @@ -26,15 +23,47 @@ void sink ( T t ) {} template void sink ( boost::array &arr ) {} -BOOST_AUTO_TEST_CASE( test_main ) -{ -// constexpr int two = arr_std.at (2); - constexpr int three = arr.at (3); - int whatever [ arr.at(4) ]; +BOOST_AUTO_TEST_CASE( test_main ) { + constexpr int three = *(arr.begin() + 3); + int whatever [ arr.back() ]; (void)three; (void) whatever; } +#ifndef BOOST_NO_CXX14_CONSTEXPR +constexpr boost::array constexpr_test_function(const boost::array& in) { + boost::array res = in; + res.front() = res.back(); + res[2] = res.at(res.size() - 2); + res[3] = *(res.data() + res[4]); + boost::get<4>(res) = boost::get<5>(res); + + return res; +} + +constexpr bool is_equal_arrays(const boost::array& lhs, const boost::array& rhs) { + for (boost::array::size_type i = 0; i < 10; ++i) { + if (lhs[i] != rhs[i]) { + return false; + } + } + + return true; +} + +BOOST_AUTO_TEST_CASE( test_constexpr_advanced ) +{ + constexpr boost::array cx14 {{ 0,1,2,3,4,5,6,7,8,9 }}; + constexpr boost::array res = constexpr_test_function(cx14); + constexpr boost::array ethalon {{ 9,1,8,4,5,5,6,7,8,9 }}; + // We can not use `operator ==` with constexpr because it uses std::equal + BOOST_STATIC_ASSERT_MSG( + (is_equal_arrays(res, ethalon)), + "Failed static assert with ethalon value" + ); +} +#endif // #ifndef BOOST_NO_CXX11_CONSTEXPR + #else // no constexpr means no constexpr tests! BOOST_AUTO_TEST_CASE( test_main ) {