/ m4 / ax_cxx_compile_stdcxx.m4
ax_cxx_compile_stdcxx.m4
   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 <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  #   Copyright (c) 2021 Jörn Heusipp <osmanx@problemloesungsmaschine.de>
  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 15
  47  
  48  dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
  49  dnl  (serial version number 13).
  50  
  51  AC_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      for alternative in ${ax_cxx_compile_alternatives}; do
 108        for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
 109          cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
 110          AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
 111                         $cachevar,
 112            [ac_save_CXX="$CXX"
 113             CXX="$CXX $switch"
 114             AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
 115              [eval $cachevar=yes],
 116              [eval $cachevar=no])
 117             CXX="$ac_save_CXX"])
 118          if eval test x\$$cachevar = xyes; then
 119            CXX="$CXX $switch"
 120            if test -n "$CXXCPP" ; then
 121              CXXCPP="$CXXCPP $switch"
 122            fi
 123            ac_success=yes
 124            break
 125          fi
 126        done
 127        if test x$ac_success = xyes; then
 128          break
 129        fi
 130      done
 131    fi])
 132    AC_LANG_POP([C++])
 133    if test x$ax_cxx_compile_cxx$1_required = xtrue; then
 134      if test x$ac_success = xno; then
 135        AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
 136      fi
 137    fi
 138    if test x$ac_success = xno; then
 139      HAVE_CXX$1=0
 140      AC_MSG_NOTICE([No compiler with C++$1 support was found])
 141    else
 142      HAVE_CXX$1=1
 143      AC_DEFINE(HAVE_CXX$1,1,
 144                [define if the compiler supports basic C++$1 syntax])
 145    fi
 146    AC_SUBST(HAVE_CXX$1)
 147  ])
 148  
 149  
 150  dnl  Test body for checking C++11 support
 151  
 152  m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
 153    _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
 154  )
 155  
 156  dnl  Test body for checking C++14 support
 157  
 158  m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
 159    _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
 160    _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
 161  )
 162  
 163  dnl  Test body for checking C++17 support
 164  
 165  m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
 166    _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
 167    _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
 168    _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
 169  )
 170  
 171  dnl  Test body for checking C++20 support
 172  
 173  m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20],
 174    _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
 175    _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
 176    _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
 177    _AX_CXX_COMPILE_STDCXX_testbody_new_in_20
 178  )
 179  
 180  
 181  dnl  Tests for new features in C++11
 182  
 183  m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
 184  
 185  // If the compiler admits that it is not ready for C++11, why torture it?
 186  // Hopefully, this will speed up the test.
 187  
 188  #ifndef __cplusplus
 189  
 190  #error "This is not a C++ compiler"
 191  
 192  // MSVC always sets __cplusplus to 199711L in older versions; newer versions
 193  // only set it correctly if /Zc:__cplusplus is specified as well as a
 194  // /std:c++NN switch:
 195  // https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
 196  #elif __cplusplus < 201103L && !defined _MSC_VER
 197  
 198  #error "This is not a C++11 compiler"
 199  
 200  #else
 201  
 202  namespace 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  
 476  dnl  Tests for new features in C++14
 477  
 478  m4_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 && !defined _MSC_VER
 488  
 489  #error "This is not a C++14 compiler"
 490  
 491  #else
 492  
 493  namespace 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  
 600  dnl  Tests for new features in C++17
 601  
 602  m4_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 && !defined _MSC_VER
 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  
 621  namespace 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 && !defined _MSC_VER
 978  
 979  ]])
 980  
 981  
 982  dnl  Tests for new features in C++20
 983  
 984  m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[
 985  
 986  #ifndef __cplusplus
 987  
 988  #error "This is not a C++ compiler"
 989  
 990  #elif __cplusplus < 202002L && !defined _MSC_VER
 991  
 992  #error "This is not a C++20 compiler"
 993  
 994  #else
 995  
 996  #include <version>
 997  
 998  namespace cxx20
 999  {
1000  
1001  // As C++20 supports feature test macros in the standard, there is no
1002  // immediate need to actually test for feature availability on the
1003  // Autoconf side.
1004  
1005  }  // namespace cxx20
1006  
1007  #endif  // __cplusplus < 202002L && !defined _MSC_VER
1008  
1009  ]])