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