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