@@ -90,6 +90,8 @@
// _GLIBCXX20_DEPRECATED_SUGGEST( string-literal )
// _GLIBCXX23_DEPRECATED
// _GLIBCXX23_DEPRECATED_SUGGEST( string-literal )
+// _GLIBCXX26_DEPRECATED
+// _GLIBCXX26_DEPRECATED_SUGGEST( string-literal )
#ifndef _GLIBCXX_USE_DEPRECATED
# define _GLIBCXX_USE_DEPRECATED 1
#endif
@@ -143,6 +145,14 @@
# define _GLIBCXX23_DEPRECATED_SUGGEST(ALT)
#endif
+#if defined(__DEPRECATED) && (__cplusplus >= 202400L)
+# define _GLIBCXX26_DEPRECATED [[__deprecated__]]
+# define _GLIBCXX26_DEPRECATED_SUGGEST(ALT) _GLIBCXX_DEPRECATED_SUGGEST(ALT)
+#else
+# define _GLIBCXX26_DEPRECATED
+# define _GLIBCXX26_DEPRECATED_SUGGEST(ALT)
+#endif
+
// Macros for ABI tag attributes.
#ifndef _GLIBCXX_ABI_TAG_CXX11
# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11")))
@@ -1171,7 +1171,7 @@ ftms = {
// 202306 P2637R3 Member visit
// 202311 P2918R2 Runtime format strings II
values = {
- v = 202305;
+ v = 202306;
cxxmin = 26;
hosted = yes;
};
@@ -1310,9 +1310,9 @@
#if !defined(__cpp_lib_format)
# if (__cplusplus > 202302L) && _GLIBCXX_HOSTED
-# define __glibcxx_format 202305L
+# define __glibcxx_format 202306L
# if defined(__glibcxx_want_all) || defined(__glibcxx_want_format)
-# define __cpp_lib_format 202305L
+# define __cpp_lib_format 202306L
# endif
# elif (__cplusplus >= 202002L) && _GLIBCXX_HOSTED
# define __glibcxx_format 202304L
@@ -3346,6 +3346,18 @@ namespace __format
explicit operator bool() const noexcept
{ return _M_type != __format::_Arg_none; }
+#if __cpp_lib_format >= 202306L // >= C++26
+ template<typename _Visitor>
+ decltype(auto)
+ visit(this basic_format_arg __arg, _Visitor&& __vis)
+ { return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type); }
+
+ template<typename _Res, typename _Visitor>
+ _Res
+ visit(this basic_format_arg __arg, _Visitor&& __vis)
+ { return __arg._M_visit(std::forward<_Visitor>(__vis), __arg._M_type); }
+#endif
+
private:
template<typename _Ctx>
friend class basic_format_args;
@@ -3631,6 +3643,7 @@ namespace __format
};
template<typename _Visitor, typename _Context>
+ _GLIBCXX26_DEPRECATED_SUGGEST("std::basic_format_arg::visit")
inline decltype(auto)
visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg)
{
@@ -3666,6 +3679,8 @@ namespace __format
}
};
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
template<typename _Context>
inline size_t
__int_from_arg(const basic_format_arg<_Context>& __arg)
@@ -4299,6 +4314,7 @@ namespace __format
else
return std::move(__sink)._M_finish().out;
}
+#pragma GCC diagnostic pop
} // namespace __format
/// @endcond
@@ -3,6 +3,8 @@
#include <format>
#include <testsuite_hooks.h>
+// { dg-warning "deprecated" "" { target c++26 } 0 }
+
template<typename Ctx, typename T>
bool equals(std::basic_format_arg<Ctx> fmt_arg, T expected) {
return std::visit_format_arg([=](auto arg_val) {
@@ -51,6 +53,9 @@ test_args()
char c = '2';
double d = 3.4;
+ // We need an lvalue of type format-arg-store<Context, Args...> for the
+ // lvalue args to point to, otherwise it will have a dangling pointer.
+ // This is not how you're supposed to use format args, just for testing.
auto store = std::make_format_args(b, i, c, d);
std::format_args args = store;
VERIFY(equals(args.get(0), false));
@@ -102,8 +107,46 @@ test_args()
VERIFY(std::visit_format_arg(is_handle, args.get(1)));
}
+void
+test_member_visit()
+{
+#if __cpp_lib_format >= 202306L // C++26 adds std::basic_format_arg::visit
+ int one = 1;
+ float two = 2.0;
+ std::string_view three = "three";
+ auto store = std::make_format_args(one, two, three); // See comment above.
+ std::format_args args = store;
+ auto a1 = args.get(0).visit([=](auto a) {
+ if constexpr (std::is_same_v<decltype(a), int>)
+ return a == one;
+ return false;
+ });
+ VERIFY( a1 );
+ auto a2 = args.get(1).visit([=](auto a) {
+ if constexpr (std::is_same_v<decltype(a), float>)
+ return a == two;
+ return false;
+ });
+ VERIFY( a2 );
+ auto a3 = args.get(2).visit([=](auto a) {
+ if constexpr (std::is_same_v<decltype(a), std::string_view>)
+ return a == three;
+ return false;
+ });
+ VERIFY( a3 );
+
+ auto a4 = args.get(0).visit<std::string_view>([](auto) { return "str"; });
+ static_assert( std::is_same_v<decltype(a4), std::string_view> );
+ VERIFY( a4 == "str" );
+ args.get(0).visit<void>([](auto){});
+ using V = decltype(args.get(0).visit<void>([](auto){}));
+ static_assert( std::is_same_v<V, void> );
+#endif
+}
+
int main()
{
test_empty();
test_args();
+ test_member_visit();
}
@@ -8,7 +8,7 @@
# error "Feature test macro for std::format is missing in <format>"
#elif __cpp_lib_format < 202110L
# error "Feature test macro for std::format has wrong value in <format>"
-#elif __cplusplus > 202302L && __cpp_lib_format < 202305L
+#elif __cplusplus > 202302L && __cpp_lib_format < 202306L
# error "Feature test macro for std::format has wrong value in <format>"
#endif
@@ -24,7 +24,7 @@
# error "Feature test macro for std::format is missing in <version>"
#elif __cpp_lib_format < 202110L
# error "Feature test macro for std::format has wrong value in <version>"
-#elif __cplusplus > 202302L && __cpp_lib_format < 202305L
+#elif __cplusplus > 202302L && __cpp_lib_format < 202306L
# error "Feature test macro for std::format has wrong value in <version>"
#endif
@@ -473,7 +473,7 @@ struct std::formatter<X, char>
std::format_context::iterator
format(X, std::format_context& c) const
{
- std::visit_format_arg([this]<typename T>(T) {
+ std::visit_format_arg([this]<typename T>(T) { // { dg-warning "deprecated" "" { target c++26 } }
if (is_integral_v<T> != this->integer)
throw std::format_error("invalid argument type");
}, c.arg(1));