ax_cxx_compile_stdcxx.m4 raw

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