1 # SPDX-License-Identifier: FSFAP 2 # =========================================================================== 3 # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html 4 # =========================================================================== 5 # 6 # SYNOPSIS 7 # 8 # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) 9 # 10 # DESCRIPTION 11 # 12 # Check for baseline language coverage in the compiler for the specified 13 # version of the C++ standard. If necessary, add switches to CXX and 14 # CXXCPP to enable support. VERSION may be '11', '14', '17', or '20' for 15 # the respective C++ standard version. 16 # 17 # The second argument, if specified, indicates whether you insist on an 18 # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. 19 # -std=c++11). If neither is specified, you get whatever works, with 20 # preference for no added switch, and then for an extended mode. 21 # 22 # The third argument, if specified 'mandatory' or if left unspecified, 23 # indicates that baseline support for the specified C++ standard is 24 # required and that the macro should error out if no mode with that 25 # support is found. If specified 'optional', then configuration proceeds 26 # regardless, after defining HAVE_CXX${VERSION} if and only if a 27 # supporting mode is found. 28 # 29 # LICENSE 30 # 31 # Copyright (c) 2008 Benjamin Kosnik <bkoz (a] redhat.com> 32 # Copyright (c) 2012 Zack Weinberg <zackw (a] panix.com> 33 # Copyright (c) 2013 Roy Stogner <roystgnr (a] ices.utexas.edu> 34 # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov (a] google.com> 35 # Copyright (c) 2015 Paul Norman <penorman (a] mac.com> 36 # Copyright (c) 2015 Moritz Klammler <moritz (a] klammler.eu> 37 # Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz (a] gmail.com> 38 # Copyright (c) 2019 Enji Cooper <yaneurabeya (a] gmail.com> 39 # Copyright (c) 2020 Jason Merrill <jason (a] redhat.com> 40 # Copyright (c) 2021 Jrn Heusipp <osmanx (a] problemloesungsmaschine.de> 41 # 42 # Copying and distribution of this file, with or without modification, are 43 # permitted in any medium without royalty provided the copyright notice 44 # and this notice are preserved. This file is offered as-is, without any 45 # warranty. 46 47 #serial 18 48 49 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro 50 dnl (serial version number 13). 51 52 AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl 53 m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], 54 [$1], [14], [ax_cxx_compile_alternatives="14 1y"], 55 [$1], [17], [ax_cxx_compile_alternatives="17 1z"], 56 [$1], [20], [ax_cxx_compile_alternatives="20"], 57 [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl 58 m4_if([$2], [], [], 59 [$2], [ext], [], 60 [$2], [noext], [], 61 [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl 62 m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], 63 [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], 64 [$3], [optional], [ax_cxx_compile_cxx$1_required=false], 65 [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) 66 AC_LANG_PUSH([C++])dnl 67 ac_success=no 68 69 m4_if([$2], [], [dnl 70 AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, 71 ax_cv_cxx_compile_cxx$1, 72 [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 73 [ax_cv_cxx_compile_cxx$1=yes], 74 [ax_cv_cxx_compile_cxx$1=no])]) 75 if test x$ax_cv_cxx_compile_cxx$1 = xyes; then 76 ac_success=yes 77 fi]) 78 79 m4_if([$2], [noext], [], [dnl 80 if test x$ac_success = xno; then 81 for alternative in ${ax_cxx_compile_alternatives}; do 82 switch="-std=gnu++${alternative}" 83 cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 84 AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 85 $cachevar, 86 [ac_save_CXX="$CXX" 87 CXX="$CXX $switch" 88 AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 89 [eval $cachevar=yes], 90 [eval $cachevar=no]) 91 CXX="$ac_save_CXX"]) 92 if eval test x\$$cachevar = xyes; then 93 CXX="$CXX $switch" 94 if test -n "$CXXCPP" ; then 95 CXXCPP="$CXXCPP $switch" 96 fi 97 ac_success=yes 98 break 99 fi 100 done 101 fi]) 102 103 m4_if([$2], [ext], [], [dnl 104 if test x$ac_success = xno; then 105 dnl HP's aCC needs +std=c++11 according to: 106 dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf 107 dnl Cray's crayCC needs "-h std=c++11" 108 dnl MSVC needs -std:c++NN for C++17 and later (default is C++14) 109 for alternative in ${ax_cxx_compile_alternatives}; do 110 for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do 111 if test x"$switch" = xMSVC; then 112 dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide 113 dnl with -std=c++17. We suffix the cache variable name with _MSVC to 114 dnl avoid this. 115 switch=-std:c++${alternative} 116 cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC]) 117 else 118 cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) 119 fi 120 AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, 121 $cachevar, 122 [ac_save_CXX="$CXX" 123 CXX="$CXX $switch" 124 AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], 125 [eval $cachevar=yes], 126 [eval $cachevar=no]) 127 CXX="$ac_save_CXX"]) 128 if eval test x\$$cachevar = xyes; then 129 CXX="$CXX $switch" 130 if test -n "$CXXCPP" ; then 131 CXXCPP="$CXXCPP $switch" 132 fi 133 ac_success=yes 134 break 135 fi 136 done 137 if test x$ac_success = xyes; then 138 break 139 fi 140 done 141 fi]) 142 AC_LANG_POP([C++]) 143 if test x$ax_cxx_compile_cxx$1_required = xtrue; then 144 if test x$ac_success = xno; then 145 AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) 146 fi 147 fi 148 if test x$ac_success = xno; then 149 HAVE_CXX$1=0 150 AC_MSG_NOTICE([No compiler with C++$1 support was found]) 151 else 152 HAVE_CXX$1=1 153 AC_DEFINE(HAVE_CXX$1,1, 154 [define if the compiler supports basic C++$1 syntax]) 155 fi 156 AC_SUBST(HAVE_CXX$1) 157 ]) 158 159 160 dnl Test body for checking C++11 support 161 162 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], 163 _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 164 ) 165 166 dnl Test body for checking C++14 support 167 168 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], 169 _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 170 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 171 ) 172 173 dnl Test body for checking C++17 support 174 175 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], 176 _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 177 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 178 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 179 ) 180 181 dnl Test body for checking C++20 support 182 183 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20], 184 _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 185 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 186 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 187 _AX_CXX_COMPILE_STDCXX_testbody_new_in_20 188 ) 189 190 191 dnl Tests for new features in C++11 192 193 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ 194 195 // If the compiler admits that it is not ready for C++11, why torture it? 196 // Hopefully, this will speed up the test. 197 198 #ifndef __cplusplus 199 200 #error "This is not a C++ compiler" 201 202 // MSVC always sets __cplusplus to 199711L in older versions; newer versions 203 // only set it correctly if /Zc:__cplusplus is specified as well as a 204 // /std:c++NN switch: 205 // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ 206 #elif __cplusplus < 201103L && !defined _MSC_VER 207 208 #error "This is not a C++11 compiler" 209 210 #else 211 212 namespace cxx11 213 { 214 215 namespace test_static_assert 216 { 217 218 template <typename T> 219 struct check 220 { 221 static_assert(sizeof(int) <= sizeof(T), "not big enough"); 222 }; 223 224 } 225 226 namespace test_final_override 227 { 228 229 struct Base 230 { 231 virtual ~Base() {} 232 virtual void f() {} 233 }; 234 235 struct Derived : public Base 236 { 237 virtual ~Derived() override {} 238 virtual void f() override {} 239 }; 240 241 } 242 243 namespace test_double_right_angle_brackets 244 { 245 246 template < typename T > 247 struct check {}; 248 249 typedef check<void> single_type; 250 typedef check<check<void>> double_type; 251 typedef check<check<check<void>>> triple_type; 252 typedef check<check<check<check<void>>>> quadruple_type; 253 254 } 255 256 namespace test_decltype 257 { 258 259 int 260 f() 261 { 262 int a = 1; 263 decltype(a) b = 2; 264 return a + b; 265 } 266 267 } 268 269 namespace test_type_deduction 270 { 271 272 template < typename T1, typename T2 > 273 struct is_same 274 { 275 static const bool value = false; 276 }; 277 278 template < typename T > 279 struct is_same<T, T> 280 { 281 static const bool value = true; 282 }; 283 284 template < typename T1, typename T2 > 285 auto 286 add(T1 a1, T2 a2) -> decltype(a1 + a2) 287 { 288 return a1 + a2; 289 } 290 291 int 292 test(const int c, volatile int v) 293 { 294 static_assert(is_same<int, decltype(0)>::value == true, ""); 295 static_assert(is_same<int, decltype(c)>::value == false, ""); 296 static_assert(is_same<int, decltype(v)>::value == false, ""); 297 auto ac = c; 298 auto av = v; 299 auto sumi = ac + av + 'x'; 300 auto sumf = ac + av + 1.0; 301 static_assert(is_same<int, decltype(ac)>::value == true, ""); 302 static_assert(is_same<int, decltype(av)>::value == true, ""); 303 static_assert(is_same<int, decltype(sumi)>::value == true, ""); 304 static_assert(is_same<int, decltype(sumf)>::value == false, ""); 305 static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); 306 return (sumf > 0.0) ? sumi : add(c, v); 307 } 308 309 } 310 311 namespace test_noexcept 312 { 313 314 int f() { return 0; } 315 int g() noexcept { return 0; } 316 317 static_assert(noexcept(f()) == false, ""); 318 static_assert(noexcept(g()) == true, ""); 319 320 } 321 322 namespace test_constexpr 323 { 324 325 template < typename CharT > 326 unsigned long constexpr 327 strlen_c_r(const CharT *const s, const unsigned long acc) noexcept 328 { 329 return *s ? strlen_c_r(s + 1, acc + 1) : acc; 330 } 331 332 template < typename CharT > 333 unsigned long constexpr 334 strlen_c(const CharT *const s) noexcept 335 { 336 return strlen_c_r(s, 0UL); 337 } 338 339 static_assert(strlen_c("") == 0UL, ""); 340 static_assert(strlen_c("1") == 1UL, ""); 341 static_assert(strlen_c("example") == 7UL, ""); 342 static_assert(strlen_c("another\0example") == 7UL, ""); 343 344 } 345 346 namespace test_rvalue_references 347 { 348 349 template < int N > 350 struct answer 351 { 352 static constexpr int value = N; 353 }; 354 355 answer<1> f(int&) { return answer<1>(); } 356 answer<2> f(const int&) { return answer<2>(); } 357 answer<3> f(int&&) { return answer<3>(); } 358 359 void 360 test() 361 { 362 int i = 0; 363 const int c = 0; 364 static_assert(decltype(f(i))::value == 1, ""); 365 static_assert(decltype(f(c))::value == 2, ""); 366 static_assert(decltype(f(0))::value == 3, ""); 367 } 368 369 } 370 371 namespace test_uniform_initialization 372 { 373 374 struct test 375 { 376 static const int zero {}; 377 static const int one {1}; 378 }; 379 380 static_assert(test::zero == 0, ""); 381 static_assert(test::one == 1, ""); 382 383 } 384 385 namespace test_lambdas 386 { 387 388 void 389 test1() 390 { 391 auto lambda1 = [](){}; 392 auto lambda2 = lambda1; 393 lambda1(); 394 lambda2(); 395 } 396 397 int 398 test2() 399 { 400 auto a = [](int i, int j){ return i + j; }(1, 2); 401 auto b = []() -> int { return '0'; }(); 402 auto c = [=](){ return a + b; }(); 403 auto d = [&](){ return c; }(); 404 auto e = [a, &b](int x) mutable { 405 const auto identity = [](int y){ return y; }; 406 for (auto i = 0; i < a; ++i) 407 a += b--; 408 return x + identity(a + b); 409 }(0); 410 return a + b + c + d + e; 411 } 412 413 int 414 test3() 415 { 416 const auto nullary = [](){ return 0; }; 417 const auto unary = [](int x){ return x; }; 418 using nullary_t = decltype(nullary); 419 using unary_t = decltype(unary); 420 const auto higher1st = [](nullary_t f){ return f(); }; 421 const auto higher2nd = [unary](nullary_t f1){ 422 return [unary, f1](unary_t f2){ return f2(unary(f1())); }; 423 }; 424 return higher1st(nullary) + higher2nd(nullary)(unary); 425 } 426 427 } 428 429 namespace test_variadic_templates 430 { 431 432 template <int...> 433 struct sum; 434 435 template <int N0, int... N1toN> 436 struct sum<N0, N1toN...> 437 { 438 static constexpr auto value = N0 + sum<N1toN...>::value; 439 }; 440 441 template <> 442 struct sum<> 443 { 444 static constexpr auto value = 0; 445 }; 446 447 static_assert(sum<>::value == 0, ""); 448 static_assert(sum<1>::value == 1, ""); 449 static_assert(sum<23>::value == 23, ""); 450 static_assert(sum<1, 2>::value == 3, ""); 451 static_assert(sum<5, 5, 11>::value == 21, ""); 452 static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); 453 454 } 455 456 // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae 457 // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function 458 // because of this. 459 namespace test_template_alias_sfinae 460 { 461 462 struct foo {}; 463 464 template<typename T> 465 using member = typename T::member_type; 466 467 template<typename T> 468 void func(...) {} 469 470 template<typename T> 471 void func(member<T>*) {} 472 473 void test(); 474 475 void test() { func<foo>(0); } 476 477 } 478 479 } // namespace cxx11 480 481 #endif // __cplusplus >= 201103L 482 483 ]]) 484 485 486 dnl Tests for new features in C++14 487 488 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ 489 490 // If the compiler admits that it is not ready for C++14, why torture it? 491 // Hopefully, this will speed up the test. 492 493 #ifndef __cplusplus 494 495 #error "This is not a C++ compiler" 496 497 #elif __cplusplus < 201402L && !defined _MSC_VER 498 499 #error "This is not a C++14 compiler" 500 501 #else 502 503 namespace cxx14 504 { 505 506 namespace test_polymorphic_lambdas 507 { 508 509 int 510 test() 511 { 512 const auto lambda = [](auto&&... args){ 513 const auto istiny = [](auto x){ 514 return (sizeof(x) == 1UL) ? 1 : 0; 515 }; 516 const int aretiny[] = { istiny(args)... }; 517 return aretiny[0]; 518 }; 519 return lambda(1, 1L, 1.0f, '1'); 520 } 521 522 } 523 524 namespace test_binary_literals 525 { 526 527 constexpr auto ivii = 0b0000000000101010; 528 static_assert(ivii == 42, "wrong value"); 529 530 } 531 532 namespace test_generalized_constexpr 533 { 534 535 template < typename CharT > 536 constexpr unsigned long 537 strlen_c(const CharT *const s) noexcept 538 { 539 auto length = 0UL; 540 for (auto p = s; *p; ++p) 541 ++length; 542 return length; 543 } 544 545 static_assert(strlen_c("") == 0UL, ""); 546 static_assert(strlen_c("x") == 1UL, ""); 547 static_assert(strlen_c("test") == 4UL, ""); 548 static_assert(strlen_c("another\0test") == 7UL, ""); 549 550 } 551 552 namespace test_lambda_init_capture 553 { 554 555 int 556 test() 557 { 558 auto x = 0; 559 const auto lambda1 = [a = x](int b){ return a + b; }; 560 const auto lambda2 = [a = lambda1(x)](){ return a; }; 561 return lambda2(); 562 } 563 564 } 565 566 namespace test_digit_separators 567 { 568 569 constexpr auto ten_million = 100'000'000; 570 static_assert(ten_million == 100000000, ""); 571 572 } 573 574 namespace test_return_type_deduction 575 { 576 577 auto f(int& x) { return x; } 578 decltype(auto) g(int& x) { return x; } 579 580 template < typename T1, typename T2 > 581 struct is_same 582 { 583 static constexpr auto value = false; 584 }; 585 586 template < typename T > 587 struct is_same<T, T> 588 { 589 static constexpr auto value = true; 590 }; 591 592 int 593 test() 594 { 595 auto x = 0; 596 static_assert(is_same<int, decltype(f(x))>::value, ""); 597 static_assert(is_same<int&, decltype(g(x))>::value, ""); 598 return x; 599 } 600 601 } 602 603 } // namespace cxx14 604 605 #endif // __cplusplus >= 201402L 606 607 ]]) 608 609 610 dnl Tests for new features in C++17 611 612 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ 613 614 // If the compiler admits that it is not ready for C++17, why torture it? 615 // Hopefully, this will speed up the test. 616 617 #ifndef __cplusplus 618 619 #error "This is not a C++ compiler" 620 621 #elif __cplusplus < 201703L && !defined _MSC_VER 622 623 #error "This is not a C++17 compiler" 624 625 #else 626 627 #include <initializer_list> 628 #include <utility> 629 #include <type_traits> 630 631 namespace cxx17 632 { 633 634 namespace test_constexpr_lambdas 635 { 636 637 constexpr int foo = [](){return 42;}(); 638 639 } 640 641 namespace test::nested_namespace::definitions 642 { 643 644 } 645 646 namespace test_fold_expression 647 { 648 649 template<typename... Args> 650 int multiply(Args... args) 651 { 652 return (args * ... * 1); 653 } 654 655 template<typename... Args> 656 bool all(Args... args) 657 { 658 return (args && ...); 659 } 660 661 } 662 663 namespace test_extended_static_assert 664 { 665 666 static_assert (true); 667 668 } 669 670 namespace test_auto_brace_init_list 671 { 672 673 auto foo = {5}; 674 auto bar {5}; 675 676 static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value); 677 static_assert(std::is_same<int, decltype(bar)>::value); 678 } 679 680 namespace test_typename_in_template_template_parameter 681 { 682 683 template<template<typename> typename X> struct D; 684 685 } 686 687 namespace test_fallthrough_nodiscard_maybe_unused_attributes 688 { 689 690 int f1() 691 { 692 return 42; 693 } 694 695 [[nodiscard]] int f2() 696 { 697 [[maybe_unused]] auto unused = f1(); 698 699 switch (f1()) 700 { 701 case 17: 702 f1(); 703 [[fallthrough]]; 704 case 42: 705 f1(); 706 } 707 return f1(); 708 } 709 710 } 711 712 namespace test_extended_aggregate_initialization 713 { 714 715 struct base1 716 { 717 int b1, b2 = 42; 718 }; 719 720 struct base2 721 { 722 base2() { 723 b3 = 42; 724 } 725 int b3; 726 }; 727 728 struct derived : base1, base2 729 { 730 int d; 731 }; 732 733 derived d1 {{1, 2}, {}, 4}; // full initialization 734 derived d2 {{}, {}, 4}; // value-initialized bases 735 736 } 737 738 namespace test_general_range_based_for_loop 739 { 740 741 struct iter 742 { 743 int i; 744 745 int& operator* () 746 { 747 return i; 748 } 749 750 const int& operator* () const 751 { 752 return i; 753 } 754 755 iter& operator++() 756 { 757 ++i; 758 return *this; 759 } 760 }; 761 762 struct sentinel 763 { 764 int i; 765 }; 766 767 bool operator== (const iter& i, const sentinel& s) 768 { 769 return i.i == s.i; 770 } 771 772 bool operator!= (const iter& i, const sentinel& s) 773 { 774 return !(i == s); 775 } 776 777 struct range 778 { 779 iter begin() const 780 { 781 return {0}; 782 } 783 784 sentinel end() const 785 { 786 return {5}; 787 } 788 }; 789 790 void f() 791 { 792 range r {}; 793 794 for (auto i : r) 795 { 796 [[maybe_unused]] auto v = i; 797 } 798 } 799 800 } 801 802 namespace test_lambda_capture_asterisk_this_by_value 803 { 804 805 struct t 806 { 807 int i; 808 int foo() 809 { 810 return [*this]() 811 { 812 return i; 813 }(); 814 } 815 }; 816 817 } 818 819 namespace test_enum_class_construction 820 { 821 822 enum class byte : unsigned char 823 {}; 824 825 byte foo {42}; 826 827 } 828 829 namespace test_constexpr_if 830 { 831 832 template <bool cond> 833 int f () 834 { 835 if constexpr(cond) 836 { 837 return 13; 838 } 839 else 840 { 841 return 42; 842 } 843 } 844 845 } 846 847 namespace test_selection_statement_with_initializer 848 { 849 850 int f() 851 { 852 return 13; 853 } 854 855 int f2() 856 { 857 if (auto i = f(); i > 0) 858 { 859 return 3; 860 } 861 862 switch (auto i = f(); i + 4) 863 { 864 case 17: 865 return 2; 866 867 default: 868 return 1; 869 } 870 } 871 872 } 873 874 namespace test_template_argument_deduction_for_class_templates 875 { 876 877 template <typename T1, typename T2> 878 struct pair 879 { 880 pair (T1 p1, T2 p2) 881 : m1 {p1}, 882 m2 {p2} 883 {} 884 885 T1 m1; 886 T2 m2; 887 }; 888 889 void f() 890 { 891 [[maybe_unused]] auto p = pair{13, 42u}; 892 } 893 894 } 895 896 namespace test_non_type_auto_template_parameters 897 { 898 899 template <auto n> 900 struct B 901 {}; 902 903 B<5> b1; 904 B<'a'> b2; 905 906 } 907 908 namespace test_structured_bindings 909 { 910 911 int arr[2] = { 1, 2 }; 912 std::pair<int, int> pr = { 1, 2 }; 913 914 auto f1() -> int(&)[2] 915 { 916 return arr; 917 } 918 919 auto f2() -> std::pair<int, int>& 920 { 921 return pr; 922 } 923 924 struct S 925 { 926 int x1 : 2; 927 volatile double y1; 928 }; 929 930 S f3() 931 { 932 return {}; 933 } 934 935 auto [ x1, y1 ] = f1(); 936 auto& [ xr1, yr1 ] = f1(); 937 auto [ x2, y2 ] = f2(); 938 auto& [ xr2, yr2 ] = f2(); 939 const auto [ x3, y3 ] = f3(); 940 941 } 942 943 namespace test_exception_spec_type_system 944 { 945 946 struct Good {}; 947 struct Bad {}; 948 949 void g1() noexcept; 950 void g2(); 951 952 template<typename T> 953 Bad 954 f(T*, T*); 955 956 template<typename T1, typename T2> 957 Good 958 f(T1*, T2*); 959 960 static_assert (std::is_same_v<Good, decltype(f(g1, g2))>); 961 962 } 963 964 namespace test_inline_variables 965 { 966 967 template<class T> void f(T) 968 {} 969 970 template<class T> inline T g(T) 971 { 972 return T{}; 973 } 974 975 template<> inline void f<>(int) 976 {} 977 978 template<> int g<>(int) 979 { 980 return 5; 981 } 982 983 } 984 985 } // namespace cxx17 986 987 #endif // __cplusplus < 201703L && !defined _MSC_VER 988 989 ]]) 990 991 992 dnl Tests for new features in C++20 993 994 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[ 995 996 #ifndef __cplusplus 997 998 #error "This is not a C++ compiler" 999 1000 #elif __cplusplus < 202002L && !defined _MSC_VER 1001 1002 #error "This is not a C++20 compiler" 1003 1004 #else 1005 1006 #include <version> 1007 1008 namespace cxx20 1009 { 1010 1011 // As C++20 supports feature test macros in the standard, there is no 1012 // immediate need to actually test for feature availability on the 1013 // Autoconf side. 1014 1015 } // namespace cxx20 1016 1017 #endif // __cplusplus < 202002L && !defined _MSC_VER 1018 1019 ]]) 1020