diff --git a/doc/array.xml b/doc/array.xml index fb1f51f..68ee5a3 100644 --- a/doc/array.xml +++ b/doc/array.xml @@ -7,6 +7,10 @@ Nicolai Josuttis + + Marshall + Clow + 2001 @@ -16,6 +20,11 @@ Nicolai M. Josuttis + + 2012 + Marshall Clow + + Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -176,6 +185,24 @@ iterator for position after the last element will not throw + + + + const_iterator + + + constant iterator for the first element + will not throw + + + + + const_iterator + + + constant iterator for position after the last element + will not throw + @@ -200,6 +227,24 @@ reverse iterator for position after the last element in reverse iteration + + + + const_reverse_iterator + + + constant reverse iterator for the first element of reverse iteration + will not throw + + + + + const_reverse_iterator + + + constant reverse iterator for position after the last element in reverse iteration + will not throw + @@ -465,6 +510,49 @@ !(x < y) + + + + + + T + + + array<T, N>& + + element of array with index Idx + Will static_assert if Idx >= N + + + + + + T + + + const array<T, N>& + + const element of array with index Idx + Will static_assert if Idx >= N + + + diff --git a/include/boost/array.hpp b/include/boost/array.hpp index fa06fa9..210c072 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) * + * 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. * 10 Mar 2010 - (mtc) fill method added, matching resolution of the standard library working group. @@ -42,12 +43,12 @@ #include #include #include +#include #include // Handles broken standard libraries better than #include #include -#include #include // FIXES for broken compilers @@ -81,15 +82,9 @@ namespace boost { const_iterator cend() const { return elems+N; } // reverse iterator support -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) +#if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; -#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) - // workaround for broken reverse_iterator in VC7 - typedef std::reverse_iterator > reverse_iterator; - typedef std::reverse_iterator > const_reverse_iterator; #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) typedef std::reverse_iterator reverse_iterator; @@ -120,19 +115,17 @@ namespace boost { // operator[] reference operator[](size_type i) { - BOOST_ASSERT_MSG( i < N, "out of range" ); - return elems[i]; + return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i]; } - const_reference operator[](size_type i) const + /*BOOST_CONSTEXPR*/ const_reference operator[](size_type i) const { - BOOST_ASSERT_MSG( i < N, "out of range" ); - return elems[i]; + return BOOST_ASSERT_MSG( i < N, "out of range" ), elems[i]; } // at() with range check - reference at(size_type i) { rangecheck(i); return elems[i]; } - const_reference at(size_type i) const { rangecheck(i); return elems[i]; } + reference at(size_type i) { return rangecheck(i), elems[i]; } + /*BOOST_CONSTEXPR*/ const_reference at(size_type i) const { return rangecheck(i), elems[i]; } // front() and back() reference front() @@ -140,7 +133,7 @@ namespace boost { return elems[0]; } - const_reference front() const + BOOST_CONSTEXPR const_reference front() const { return elems[0]; } @@ -150,15 +143,15 @@ namespace boost { return elems[N-1]; } - const_reference back() const + BOOST_CONSTEXPR const_reference back() const { return elems[N-1]; } // size is constant - static size_type size() { return N; } - static bool empty() { return false; } - static size_type max_size() { return N; } + static BOOST_CONSTEXPR size_type size() { return N; } + static BOOST_CONSTEXPR bool empty() { return false; } + static BOOST_CONSTEXPR size_type max_size() { return N; } enum { static_size = N }; // swap (note: linear complexity) @@ -189,16 +182,12 @@ namespace boost { } // check range (may be private because it is static) - static void rangecheck (size_type i) { - if (i >= size()) { - std::out_of_range e("array<>: index out of range"); - boost::throw_exception(e); - } + static BOOST_CONSTEXPR bool rangecheck (size_type i) { + return i > size() ? boost::throw_exception(std::out_of_range ("array<>: index out of range")), true : true; } }; -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) template< class T > class array< T, 0 > { @@ -222,15 +211,9 @@ namespace boost { const_iterator cend() const { return cbegin(); } // reverse iterator support -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) +#if !defined(BOOST_MSVC_STD_ITERATOR) && !defined(BOOST_NO_STD_ITERATOR_TRAITS) typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; -#elif defined(_MSC_VER) && (_MSC_VER == 1300) && defined(BOOST_DINKUMWARE_STDLIB) && (BOOST_DINKUMWARE_STDLIB == 310) - // workaround for broken reverse_iterator in VC7 - typedef std::reverse_iterator > reverse_iterator; - typedef std::reverse_iterator > const_reverse_iterator; #elif defined(_RWSTD_NO_CLASS_PARTIAL_SPEC) typedef std::reverse_iterator reverse_iterator; @@ -264,14 +247,14 @@ namespace boost { return failed_rangecheck(); } - const_reference operator[](size_type /*i*/) const + /*BOOST_CONSTEXPR*/ const_reference operator[](size_type /*i*/) const { return failed_rangecheck(); } // at() with range check reference at(size_type /*i*/) { return failed_rangecheck(); } - const_reference at(size_type /*i*/) const { return failed_rangecheck(); } + /*BOOST_CONSTEXPR*/ const_reference at(size_type /*i*/) const { return failed_rangecheck(); } // front() and back() reference front() @@ -279,7 +262,7 @@ namespace boost { return failed_rangecheck(); } - const_reference front() const + BOOST_CONSTEXPR const_reference front() const { return failed_rangecheck(); } @@ -289,15 +272,15 @@ namespace boost { return failed_rangecheck(); } - const_reference back() const + BOOST_CONSTEXPR const_reference back() const { return failed_rangecheck(); } // size is constant - static size_type size() { return 0; } - static bool empty() { return true; } - static size_type max_size() { return 0; } + static BOOST_CONSTEXPR size_type size() { return 0; } + static BOOST_CONSTEXPR bool empty() { return true; } + static BOOST_CONSTEXPR size_type max_size() { return 0; } enum { static_size = 0 }; void swap (array& /*y*/) { @@ -335,7 +318,6 @@ namespace boost { #endif } }; -#endif // comparisons template @@ -391,7 +373,7 @@ namespace boost { // Specific for boost::array: simply returns its elems data member. template - typename const detail::c_array::type& get_c_array(const boost::array& arg) + typename detail::c_array::type const& get_c_array(const boost::array& arg) { return arg.elems; } @@ -429,6 +411,7 @@ namespace boost { } #endif + template std::size_t hash_range(It, It); template std::size_t hash_value(const array& arr) @@ -436,8 +419,36 @@ namespace boost { return boost::hash_range(arr.begin(), arr.end()); } + template + 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_STATIC_ASSERT_MSG ( Idx < N, "boost::get<>(const boost::array &) index out of range" ); + return arr[Idx]; + } + } /* namespace boost */ +#ifndef BOOST_NO_CXX11_HDR_ARRAY +// If we don't have std::array, I'm assuming that we don't have std::get +namespace std { + template + T &get(boost::array &arr) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(boost::array &) index out of range" ); + return arr[Idx]; + } + + template + const T &get(const boost::array &arr) BOOST_NOEXCEPT { + BOOST_STATIC_ASSERT_MSG ( Idx < N, "std::get<>(const boost::array &) index out of range" ); + return arr[Idx]; + } +} +#endif #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) # pragma warning(pop) diff --git a/meta/libraries.json b/meta/libraries.json new file mode 100644 index 0000000..7710ee2 --- /dev/null +++ b/meta/libraries.json @@ -0,0 +1,17 @@ +{ + "key": "array", + "name": "Array", + "authors": [ + "Nicolai Josuttis" + ], + "description": "STL compliant container wrapper for arrays of constant size.", + "std": [ + "tr1" + ], + "category": [ + "Containers" + ], + "maintainers": [ + "Marshall Clow " + ] +} diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5037474..1a04d91 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -17,5 +17,9 @@ test-suite array : [ run array4.cpp ] [ 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 ] + [ compile-fail array_getfail1.cpp ] + [ compile-fail array_getfail2.cpp ] [ run array_hash.cpp unit_test_framework : : : : array_hash ] ; diff --git a/test/array7.cpp b/test/array7.cpp new file mode 100644 index 0000000..de2ebe0 --- /dev/null +++ b/test/array7.cpp @@ -0,0 +1,67 @@ +/* tests using std::get on boost:array + * (C) Copyright Marshall Clow 2012 + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#include +#include +#include +#include +#ifndef BOOST_NO_CXX11_HDR_ARRAY +#include +#endif + +#define BOOST_TEST_MAIN +#include + +namespace { + + #ifndef BOOST_NO_CXX11_HDR_ARRAY + template< class T > + void RunStdTests() + { + typedef boost::array< T, 5 > test_type; + typedef T arr[5]; + test_type test_case; // = { 1, 1, 2, 3, 5 }; + + T &aRef = std::get<0> ( test_case ); + BOOST_CHECK ( &*test_case.begin () == &aRef ); + + const T &caRef = std::get<0> ( test_case ); + BOOST_CHECK ( &*test_case.cbegin () == &caRef ); + } + #endif + + template< class T > + void RunBoostTests() + { + typedef boost::array< T, 5 > test_type; + typedef T arr[5]; + test_type test_case; // = { 1, 1, 2, 3, 5 }; + + T &aRef = boost::get<0> ( test_case ); + BOOST_CHECK ( &*test_case.begin () == &aRef ); + + const T &caRef = boost::get<0> ( test_case ); + BOOST_CHECK ( &*test_case.cbegin () == &caRef ); + } + +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + RunBoostTests< bool >(); + RunBoostTests< void * >(); + RunBoostTests< long double >(); + RunBoostTests< std::string >(); + +#ifndef BOOST_NO_CXX11_HDR_ARRAY + RunStdTests< bool >(); + RunStdTests< void * >(); + RunStdTests< long double >(); + RunStdTests< std::string >(); +#endif +} + diff --git a/test/array_constexpr.cpp b/test/array_constexpr.cpp new file mode 100644 index 0000000..927bdec --- /dev/null +++ b/test/array_constexpr.cpp @@ -0,0 +1,42 @@ +/* tests using constexpr on boost:array + * (C) Copyright Marshall Clow 2012 + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#include +#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 ) {} + +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) ]; + (void)three; + (void) whatever; +} + +#else // no constexpr means no constexpr tests! +BOOST_AUTO_TEST_CASE( test_main ) +{ +} +#endif diff --git a/test/array_getfail1.cpp b/test/array_getfail1.cpp new file mode 100644 index 0000000..21ae62f --- /dev/null +++ b/test/array_getfail1.cpp @@ -0,0 +1,49 @@ +/* tests using std::get on boost:array + * (C) Copyright Marshall Clow 2012 + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#include +#include + + +#include +#include +#include +#ifndef BOOST_NO_CXX11_HDR_ARRAY +#include +#endif + +#define BOOST_TEST_MAIN +#include + +namespace { + + #ifndef BOOST_NO_CXX11_HDR_ARRAY + template< class T > + void RunStdTests() + { + typedef boost::array< T, 5 > test_type; + typedef T arr[5]; + test_type test_case; // = { 1, 1, 2, 3, 5 }; + + T &aRef = std::get<5> ( test_case ); // should fail to compile + BOOST_CHECK ( &*test_case.begin () == &aRef ); + } + #endif + +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ +#ifndef BOOST_NO_CXX11_HDR_ARRAY + RunStdTests< bool >(); + RunStdTests< void * >(); + RunStdTests< long double >(); + RunStdTests< std::string >(); +#else + BOOST_STATIC_ASSERT ( false ); // fail on C++03 systems. +#endif +} diff --git a/test/array_getfail2.cpp b/test/array_getfail2.cpp new file mode 100644 index 0000000..e2277b0 --- /dev/null +++ b/test/array_getfail2.cpp @@ -0,0 +1,64 @@ +/* tests using std::get on boost:array + * (C) Copyright Marshall Clow 2012 + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + */ + +#include +#include +#include +#include +#ifndef BOOST_NO_CXX11_HDR_ARRAY +#include +#endif + +#define BOOST_TEST_MAIN +#include + +namespace { + + #ifndef BOOST_NO_CXX11_HDR_ARRAY + template< class T > + void RunStdTests() + { + typedef boost::array< T, 5 > test_type; + typedef T arr[5]; + test_type test_case; // = { 1, 1, 2, 3, 5 }; + + T &aRef = std::get<0> ( test_case ); + BOOST_CHECK ( &*test_case.begin () == &aRef ); + + const T &caRef = std::get<0> ( test_case ); + BOOST_CHECK ( &*test_case.cbegin () == &caRef ); + } + #endif + + template< class T > + void RunBoostTests() + { + typedef boost::array< T, 5 > test_type; + typedef T arr[5]; + test_type test_case; // = { 1, 1, 2, 3, 5 }; + + T &aRef = boost::get<5> ( test_case ); + BOOST_CHECK ( &*test_case.begin () == &aRef ); + } + +} + +BOOST_AUTO_TEST_CASE( test_main ) +{ + RunBoostTests< bool >(); + RunBoostTests< void * >(); + RunBoostTests< long double >(); + RunBoostTests< std::string >(); + +#ifndef BOOST_NO_CXX11_HDR_ARRAY + RunStdTests< bool >(); + RunStdTests< void * >(); + RunStdTests< long double >(); + RunStdTests< std::string >(); +#endif +} +