Index: include/algorithm =================================================================== --- include/algorithm +++ include/algorithm @@ -1672,7 +1672,8 @@ _Size __count, const _Tp& __value_, _BinaryPredicate __pred) { return _VSTD::__search_n::type> - (__first, __last, __count, __value_, __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); + (__first, __last, _VSTD::__convert_to_integral(__count), __value_, + __pred, typename iterator_traits<_ForwardIterator>::iterator_category()); } template @@ -1681,7 +1682,8 @@ search_n(_ForwardIterator __first, _ForwardIterator __last, _Size __count, const _Tp& __value_) { typedef typename iterator_traits<_ForwardIterator>::value_type __v; - return _VSTD::search_n(__first, __last, __count, __value_, __equal_to<__v, _Tp>()); + return _VSTD::search_n(__first, __last, _VSTD::__convert_to_integral(__count), + __value_, __equal_to<__v, _Tp>()); } // copy @@ -1839,8 +1841,10 @@ !__is_random_access_iterator<_InputIterator>::value, _OutputIterator >::type -copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) +copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) { + typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; + _IntegralSize __n = __orig_n; if (__n > 0) { *__result = *__first; @@ -1862,8 +1866,10 @@ __is_random_access_iterator<_InputIterator>::value, _OutputIterator >::type -copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) +copy_n(_InputIterator __first, _Size __orig_n, _OutputIterator __result) { + typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; + _IntegralSize __n = __orig_n; return _VSTD::copy(__first, __first + __n, __result); } @@ -2055,7 +2061,7 @@ _OutputIterator fill_n(_OutputIterator __first, _Size __n, const _Tp& __value_) { - return _VSTD::__fill_n(__first, __n, __value_); + return _VSTD::__fill_n(__first, _VSTD::__convert_to_integral(__n), __value_); } // fill @@ -2101,8 +2107,10 @@ template inline _LIBCPP_INLINE_VISIBILITY _OutputIterator -generate_n(_OutputIterator __first, _Size __n, _Generator __gen) +generate_n(_OutputIterator __first, _Size __orig_n, _Generator __gen) { + typedef decltype(_VSTD::__convert_to_integral(__orig_n)) _IntegralSize; + _IntegralSize __n = __orig_n; for (; __n > 0; ++__first, (void) --__n) *__first = __gen(); return __first; Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -3646,6 +3646,52 @@ #endif // _LIBCPP_UNDERLYING_TYPE + +template ::value> +struct __sfinae_underlying_type +{ + typedef typename underlying_type<_Tp>::type type; + typedef decltype(((type)1) + 0) __promoted_type; +}; + +template +struct __sfinae_underlying_type<_Tp, false> +{ +}; + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +int __convert_to_integral(char __val) { return __val; } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +int __convert_to_integral(int __val) { return __val; } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +unsigned __convert_to_integral(unsigned __val) { return __val; } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +long __convert_to_integral(long __val) { return __val; } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +unsigned long __convert_to_integral(unsigned long __val) { return __val; } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +long long __convert_to_integral(long long __val) { return __val; } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +unsigned long long __convert_to_integral(unsigned long long __val) {return __val; } + +#ifndef _LIBCPP_HAS_NO_INT128 +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +__int128_t __convert_to_integral(__int128_t __val) { return __val; } + +inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_ALWAYS_INLINE +__uint128_t __convert_to_integral(__uint128_t __val) { return __val; } +#endif + +template +typename __sfinae_underlying_type<_Tp>::__promoted_type +__convert_to_integral(_Tp __val) { return __val; } + #ifndef _LIBCPP_HAS_NO_ADVANCED_SFINAE template Index: test/libcxx/type_traits/convert_to_integral.pass.cpp =================================================================== --- test/libcxx/type_traits/convert_to_integral.pass.cpp +++ test/libcxx/type_traits/convert_to_integral.pass.cpp @@ -63,6 +63,10 @@ check_integral_types(); check_integral_types(); check_integral_types(); - // TODO(ericwf): Not standard +#ifndef _LIBCPP_HAS_NO_INT128 + check_integral_types<__int128_t, __int128_t>(); + check_integral_types<__uint128_t, __uint128_t>(); +#endif + // TODO(ericwf): Not standard check_enum_types(); } \ No newline at end of file Index: test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp =================================================================== --- test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp +++ test/std/algorithms/alg.modifying.operations/alg.copy/copy_n.pass.cpp @@ -18,6 +18,14 @@ #include "test_iterators.h" +struct IntegralConvertible +{ + IntegralConvertible() : value(0) {} + explicit IntegralConvertible(int x) : value(x) {} + operator int() const { return value; } + int value; +}; + template void test() @@ -28,7 +36,7 @@ ia[i] = i; int ib[N] = {0}; - OutIter r = std::copy_n(InIter(ia), N/2, OutIter(ib)); + OutIter r = std::copy_n(InIter(ia), IntegralConvertible(N/2), OutIter(ib)); assert(base(r) == ib+N/2); for (unsigned i = 0; i < N/2; ++i) assert(ia[i] == ib[i]); Index: test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp =================================================================== --- test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp +++ test/std/algorithms/alg.modifying.operations/alg.fill/fill_n.pass.cpp @@ -19,13 +19,23 @@ #include "test_iterators.h" + +struct IntegralConvertible +{ + IntegralConvertible() : value(0) {} + explicit IntegralConvertible(int x) : value(x) {} + operator int() const { return value; } + int value; +}; + + template void test_char() { const unsigned n = 4; char ca[n] = {0}; - assert(std::fill_n(Iter(ca), n, char(1)) == std::next(Iter(ca), n)); + assert(std::fill_n(Iter(ca), IntegralConvertible(n), char(1)) == std::next(Iter(ca), n)); assert(ca[0] == 1); assert(ca[1] == 1); assert(ca[2] == 1); @@ -38,7 +48,7 @@ { const unsigned n = 4; int ia[n] = {0}; - assert(std::fill_n(Iter(ia), n, 1) == std::next(Iter(ia), n)); + assert(std::fill_n(Iter(ia), IntegralConvertible(n), 1) == std::next(Iter(ia), n)); assert(ia[0] == 1); assert(ia[1] == 1); assert(ia[2] == 1); @@ -50,7 +60,7 @@ { const unsigned n = 4; int ia[n] = {0}; - assert(std::fill_n(ia, n, static_cast(1)) == std::next(ia, n)); + assert(std::fill_n(ia, IntegralConvertible(n), static_cast(1)) == std::next(ia, n)); assert(ia[0] == 1); assert(ia[1] == 1); assert(ia[2] == 1); @@ -69,7 +79,7 @@ { const unsigned n = 4; int ia[n] = {0}; - assert(std::fill_n(ia, n, source()) == std::next(ia, n)); + assert(std::fill_n(ia, IntegralConvertible(n), source()) == std::next(ia, n)); assert(ia[0] == 0); assert(ia[1] == 1); assert(ia[2] == 2); @@ -87,7 +97,7 @@ { const unsigned n = 4; test1 test1a[n] = {0}; - assert(std::fill_n(test1a, n, static_cast(10)) == std::next(test1a, n)); + assert(std::fill_n(test1a, IntegralConvertible(n), static_cast(10)) == std::next(test1a, n)); assert(test1a[0].c == 11); assert(test1a[1].c == 11); assert(test1a[2].c == 11); @@ -110,7 +120,7 @@ test5() { A a[3]; - assert(std::fill_n(&a[0], 3, A('a')) == a+3); + assert(std::fill_n(&a[0], IntegralConvertible(3), A('a')) == a+3); assert(a[0] == A('a')); assert(a[1] == A('a')); assert(a[2] == A('a')); @@ -124,11 +134,11 @@ unsigned char b; }; }; - + void test6() { Storage foo[5]; - std::fill_n(&foo[0], 5, Storage()); + std::fill_n(&foo[0], IntegralConvertible(5), Storage()); } @@ -143,7 +153,7 @@ test_int >(); test_int >(); test_int(); - + test_int_array(); test_int_array_struct_source(); test_struct_array(); Index: test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp =================================================================== --- test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp +++ test/std/algorithms/alg.modifying.operations/alg.generate/generate_n.pass.cpp @@ -20,6 +20,14 @@ #include "test_iterators.h" +struct IntegralConvertible +{ + IntegralConvertible() : value(0) {} + explicit IntegralConvertible(int x) : value(x) {} + operator int() const { return value; } + int value; +}; + struct gen_test { int operator()() const {return 2;} @@ -31,7 +39,7 @@ { const unsigned n = 4; int ia[n] = {0}; - assert(std::generate_n(Iter(ia), n, gen_test()) == Iter(ia+n)); + assert(std::generate_n(Iter(ia), IntegralConvertible(n), gen_test()) == Iter(ia+n)); assert(ia[0] == 2); assert(ia[1] == 2); assert(ia[2] == 2); Index: test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp =================================================================== --- test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp +++ test/std/algorithms/alg.nonmodifying/alg.search/search_n.pass.cpp @@ -19,6 +19,14 @@ #include "test_iterators.h" +struct IntegralConvertible +{ + IntegralConvertible() : value(0) {} + explicit IntegralConvertible(int x) : value(x) {} + operator int() const { return value; } + int value; +}; + template void test() @@ -63,6 +71,9 @@ assert(std::search_n(Iter(ic), Iter(ic+sc), 2, 0) == Iter(ic)); assert(std::search_n(Iter(ic), Iter(ic+sc), 3, 0) == Iter(ic)); assert(std::search_n(Iter(ic), Iter(ic+sc), 4, 0) == Iter(ic+sc)); + + // Check that we properly convert the size argument to an integral. + std::search_n(Iter(ic), Iter(ic+sc), IntegralConvertible(0), 0); } int main() Index: test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp =================================================================== --- test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp +++ test/std/algorithms/alg.nonmodifying/alg.search/search_n_pred.pass.cpp @@ -29,6 +29,16 @@ unsigned count_equal::count = 0; + +struct IntegralConvertible +{ + IntegralConvertible() : value(0) {} + explicit IntegralConvertible(int x) : value(x) {} + operator int() const { return value; } + int value; +}; + + template void test() @@ -138,6 +148,10 @@ assert(std::search_n(Iter(ic), Iter(ic+sc), 4, 0, count_equal()) == Iter(ic+sc)); assert(count_equal::count <= sc); count_equal::count = 0; + + // Check that we properly convert the size argument to an integral. + std::search_n(Iter(ic), Iter(ic+sc), IntegralConvertible(4), 0, count_equal()); + count_equal::count = 0; } int main()