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 )
{