-// { dg-options "-std=gnu++14" }
-// { dg-do run }
+// { dg-do run { target c++14 } }
-// Copyright (C) 2014-2016 Free Software Foundation, Inc.
+// Copyright (C) 2014-2024 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
using std::experimental::any;
using std::experimental::any_cast;
+using std::experimental::bad_any_cast;
void test01()
{
any x(5); // x holds int
VERIFY(any_cast<int>(x) == 5); // cast to value
any_cast<int&>(x) = 10; // cast to reference
- VERIFY(any_cast<int>(x) == 10);
+ VERIFY(any_cast<int>(x) == 10);
x = "Meow"; // x holds const char*
VERIFY(strcmp(any_cast<const char*>(x), "Meow") == 0);
x = string("Meow"); // x holds string
string s, s2("Jane");
- s = move(any_cast<string&>(x)); // move from any
+ s = move(any_cast<string&>(x)); // move from any
VERIFY(s == "Meow");
any_cast<string&>(x) = move(s2); // move to any
VERIFY(any_cast<const string&>(x) == "Jane");
void test02()
{
- using std::experimental::bad_any_cast;
any x(1);
auto p = any_cast<double>(&x);
VERIFY(p == nullptr);
}
}
+static int move_count = 0;
+
+void test03()
+{
+ struct MoveEnabled
+ {
+ MoveEnabled(MoveEnabled&&)
+ {
+ ++move_count;
+ }
+ MoveEnabled() = default;
+ MoveEnabled(const MoveEnabled&) = default;
+ };
+ MoveEnabled m;
+ MoveEnabled m2 = any_cast<MoveEnabled>(any(m));
+ VERIFY(move_count == 1);
+ MoveEnabled&& m3 = any_cast<MoveEnabled&&>(any(m));
+ VERIFY(move_count == 1);
+ struct MoveDeleted
+ {
+ MoveDeleted(MoveDeleted&&) = delete;
+ MoveDeleted() = default;
+ MoveDeleted(const MoveDeleted&) = default;
+ };
+ MoveDeleted md;
+ MoveDeleted&& md2 = any_cast<MoveDeleted>(any(std::move(md)));
+ MoveDeleted&& md3 = any_cast<MoveDeleted&&>(any(std::move(md)));
+}
+
+void test05()
+{
+ // PR libstdc++/69321
+ struct noncopyable {
+ noncopyable(noncopyable const&) = delete;
+ };
+
+ any a;
+ auto p = any_cast<noncopyable>(&a);
+ VERIFY( p == nullptr );
+}
+
+void test06()
+{
+ // The contained value of a std::any is always an object type,
+ // but any_cast does not forbid checking for function types.
+
+ any a(1);
+ void (*p1)() = any_cast<void()>(&a);
+ VERIFY( p1 == nullptr );
+ int (*p2)(int) = any_cast<int(int)>(&a);
+ VERIFY( p2 == nullptr );
+ int (*p3)() = any_cast<int()>(&const_cast<const any&>(a));
+ VERIFY( p3 == nullptr );
+
+ try {
+ any_cast<int(&)()>(a);
+ VERIFY( false );
+ } catch (const bad_any_cast&) {
+ }
+
+ try {
+ any_cast<int(&)()>(std::move(a));
+ VERIFY( false );
+ } catch (const bad_any_cast&) {
+ }
+
+ try {
+ any_cast<int(&)()>(const_cast<const any&>(a));
+ VERIFY( false );
+ } catch (const bad_any_cast&) {
+ }
+}
+
+void test07()
+{
+ int arr[3];
+ any a(arr);
+#if __cpp_rtti
+ VERIFY( a.type() == typeid(int*) ); // contained value is decayed
+#endif
+
+ int (*p1)[3] = any_cast<int[3]>(&a);
+#if __cpp_rtti
+ VERIFY( a.type() != typeid(int[3]) ); // so any_cast should return nullptr
+#endif
+ VERIFY( p1 == nullptr );
+ int (*p2)[] = any_cast<int[]>(&a);
+#if __cpp_rtti
+ VERIFY( a.type() != typeid(int[]) ); // so any_cast should return nullptr
+#endif
+ VERIFY( p2 == nullptr );
+ const int (*p3)[] = any_cast<int[]>(&const_cast<const any&>(a));
+ VERIFY( p3 == nullptr );
+}
+
int main()
{
test01();
test02();
+ test03();
+ test05();
+ test06();
+ test07();
}