16842f52aSArthur O'Dwyer //===----------------------------------------------------------------------===//
26842f52aSArthur O'Dwyer //
36842f52aSArthur O'Dwyer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46842f52aSArthur O'Dwyer // See https://llvm.org/LICENSE.txt for license information.
56842f52aSArthur O'Dwyer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66842f52aSArthur O'Dwyer //
76842f52aSArthur O'Dwyer //===----------------------------------------------------------------------===//
86842f52aSArthur O'Dwyer
96842f52aSArthur O'Dwyer // UNSUPPORTED: c++03, c++11, c++14, c++17
106842f52aSArthur O'Dwyer
116842f52aSArthur O'Dwyer // std::ranges::ssize
126842f52aSArthur O'Dwyer
136842f52aSArthur O'Dwyer #include <ranges>
146842f52aSArthur O'Dwyer
156842f52aSArthur O'Dwyer #include <cassert>
166842f52aSArthur O'Dwyer #include "test_macros.h"
176842f52aSArthur O'Dwyer #include "test_iterators.h"
186842f52aSArthur O'Dwyer
196842f52aSArthur O'Dwyer using RangeSSizeT = decltype(std::ranges::ssize);
206842f52aSArthur O'Dwyer
216842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeSSizeT, int[]>);
226842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeSSizeT, int[1]>);
236842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeSSizeT, int (&&)[1]>);
246842f52aSArthur O'Dwyer static_assert( std::is_invocable_v<RangeSSizeT, int (&)[1]>);
256842f52aSArthur O'Dwyer
266842f52aSArthur O'Dwyer struct SizeMember {
sizeSizeMember27fb855eb9SMark de Wever constexpr std::size_t size() { return 42; }
286842f52aSArthur O'Dwyer };
296842f52aSArthur O'Dwyer static_assert(!std::is_invocable_v<decltype(std::ranges::ssize), const SizeMember&>);
306842f52aSArthur O'Dwyer
316842f52aSArthur O'Dwyer struct SizeFunction {
size(SizeFunction)32fb855eb9SMark de Wever friend constexpr std::size_t size(SizeFunction) { return 42; }
336842f52aSArthur O'Dwyer };
346842f52aSArthur O'Dwyer
356842f52aSArthur O'Dwyer struct SizeFunctionSigned {
size(SizeFunctionSigned)366842f52aSArthur O'Dwyer friend constexpr std::ptrdiff_t size(SizeFunctionSigned) { return 42; }
376842f52aSArthur O'Dwyer };
386842f52aSArthur O'Dwyer
396842f52aSArthur O'Dwyer struct SizedSentinelRange {
406842f52aSArthur O'Dwyer int data_[2] = {};
beginSizedSentinelRange416842f52aSArthur O'Dwyer constexpr int *begin() { return data_; }
endSizedSentinelRange426842f52aSArthur O'Dwyer constexpr auto end() { return sized_sentinel<int*>(data_ + 2); }
436842f52aSArthur O'Dwyer };
446842f52aSArthur O'Dwyer
456842f52aSArthur O'Dwyer struct ShortUnsignedReturnType {
sizeShortUnsignedReturnType466842f52aSArthur O'Dwyer constexpr unsigned short size() { return 42; }
476842f52aSArthur O'Dwyer };
486842f52aSArthur O'Dwyer
496842f52aSArthur O'Dwyer // size_t changes depending on the platform.
50fb855eb9SMark de Wever using SignedSizeT = std::make_signed_t<std::size_t>;
516842f52aSArthur O'Dwyer
test()526842f52aSArthur O'Dwyer constexpr bool test() {
536842f52aSArthur O'Dwyer int a[4];
546842f52aSArthur O'Dwyer
556842f52aSArthur O'Dwyer assert(std::ranges::ssize(a) == 4);
566842f52aSArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::ssize(a)), SignedSizeT);
576842f52aSArthur O'Dwyer
586842f52aSArthur O'Dwyer assert(std::ranges::ssize(SizeMember()) == 42);
596842f52aSArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeMember())), SignedSizeT);
606842f52aSArthur O'Dwyer
616842f52aSArthur O'Dwyer assert(std::ranges::ssize(SizeFunction()) == 42);
626842f52aSArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunction())), SignedSizeT);
636842f52aSArthur O'Dwyer
646842f52aSArthur O'Dwyer assert(std::ranges::ssize(SizeFunctionSigned()) == 42);
656842f52aSArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunctionSigned())), std::ptrdiff_t);
666842f52aSArthur O'Dwyer
676842f52aSArthur O'Dwyer SizedSentinelRange b;
686842f52aSArthur O'Dwyer assert(std::ranges::ssize(b) == 2);
696842f52aSArthur O'Dwyer ASSERT_SAME_TYPE(decltype(std::ranges::ssize(b)), std::ptrdiff_t);
706842f52aSArthur O'Dwyer
716842f52aSArthur O'Dwyer // This gets converted to ptrdiff_t because it's wider.
726842f52aSArthur O'Dwyer ShortUnsignedReturnType c;
736842f52aSArthur O'Dwyer assert(std::ranges::ssize(c) == 42);
74*d8681356SMark de Wever ASSERT_SAME_TYPE(decltype(std::ranges::ssize(c)), std::ptrdiff_t);
756842f52aSArthur O'Dwyer
766842f52aSArthur O'Dwyer return true;
776842f52aSArthur O'Dwyer }
786842f52aSArthur O'Dwyer
7985073836SArthur O'Dwyer // Test ADL-proofing.
8085073836SArthur O'Dwyer struct Incomplete;
8185073836SArthur O'Dwyer template<class T> struct Holder { T t; };
8285073836SArthur O'Dwyer static_assert(!std::is_invocable_v<RangeSSizeT, Holder<Incomplete>*>);
839be193bcSArthur O'Dwyer static_assert(!std::is_invocable_v<RangeSSizeT, Holder<Incomplete>*&>);
8485073836SArthur O'Dwyer
main(int,char **)856842f52aSArthur O'Dwyer int main(int, char**) {
866842f52aSArthur O'Dwyer test();
876842f52aSArthur O'Dwyer static_assert(test());
886842f52aSArthur O'Dwyer
896842f52aSArthur O'Dwyer return 0;
906842f52aSArthur O'Dwyer }
91