[TESTS] Fix node::operator< in time_antipode.cpp.
[ginac.git] / 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 14
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 #elif __cplusplus < 201103L
193
194 #error "This is not a C++11 compiler"
195
196 #else
197
198 namespace cxx11
199 {
200
201   namespace test_static_assert
202   {
203
204     template <typename T>
205     struct check
206     {
207       static_assert(sizeof(int) <= sizeof(T), "not big enough");
208     };
209
210   }
211
212   namespace test_final_override
213   {
214
215     struct Base
216     {
217       virtual ~Base() {}
218       virtual void f() {}
219     };
220
221     struct Derived : public Base
222     {
223       virtual ~Derived() override {}
224       virtual void f() override {}
225     };
226
227   }
228
229   namespace test_double_right_angle_brackets
230   {
231
232     template < typename T >
233     struct check {};
234
235     typedef check<void> single_type;
236     typedef check<check<void>> double_type;
237     typedef check<check<check<void>>> triple_type;
238     typedef check<check<check<check<void>>>> quadruple_type;
239
240   }
241
242   namespace test_decltype
243   {
244
245     int
246     f()
247     {
248       int a = 1;
249       decltype(a) b = 2;
250       return a + b;
251     }
252
253   }
254
255   namespace test_type_deduction
256   {
257
258     template < typename T1, typename T2 >
259     struct is_same
260     {
261       static const bool value = false;
262     };
263
264     template < typename T >
265     struct is_same<T, T>
266     {
267       static const bool value = true;
268     };
269
270     template < typename T1, typename T2 >
271     auto
272     add(T1 a1, T2 a2) -> decltype(a1 + a2)
273     {
274       return a1 + a2;
275     }
276
277     int
278     test(const int c, volatile int v)
279     {
280       static_assert(is_same<int, decltype(0)>::value == true, "");
281       static_assert(is_same<int, decltype(c)>::value == false, "");
282       static_assert(is_same<int, decltype(v)>::value == false, "");
283       auto ac = c;
284       auto av = v;
285       auto sumi = ac + av + 'x';
286       auto sumf = ac + av + 1.0;
287       static_assert(is_same<int, decltype(ac)>::value == true, "");
288       static_assert(is_same<int, decltype(av)>::value == true, "");
289       static_assert(is_same<int, decltype(sumi)>::value == true, "");
290       static_assert(is_same<int, decltype(sumf)>::value == false, "");
291       static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
292       return (sumf > 0.0) ? sumi : add(c, v);
293     }
294
295   }
296
297   namespace test_noexcept
298   {
299
300     int f() { return 0; }
301     int g() noexcept { return 0; }
302
303     static_assert(noexcept(f()) == false, "");
304     static_assert(noexcept(g()) == true, "");
305
306   }
307
308   namespace test_constexpr
309   {
310
311     template < typename CharT >
312     unsigned long constexpr
313     strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
314     {
315       return *s ? strlen_c_r(s + 1, acc + 1) : acc;
316     }
317
318     template < typename CharT >
319     unsigned long constexpr
320     strlen_c(const CharT *const s) noexcept
321     {
322       return strlen_c_r(s, 0UL);
323     }
324
325     static_assert(strlen_c("") == 0UL, "");
326     static_assert(strlen_c("1") == 1UL, "");
327     static_assert(strlen_c("example") == 7UL, "");
328     static_assert(strlen_c("another\0example") == 7UL, "");
329
330   }
331
332   namespace test_rvalue_references
333   {
334
335     template < int N >
336     struct answer
337     {
338       static constexpr int value = N;
339     };
340
341     answer<1> f(int&)       { return answer<1>(); }
342     answer<2> f(const int&) { return answer<2>(); }
343     answer<3> f(int&&)      { return answer<3>(); }
344
345     void
346     test()
347     {
348       int i = 0;
349       const int c = 0;
350       static_assert(decltype(f(i))::value == 1, "");
351       static_assert(decltype(f(c))::value == 2, "");
352       static_assert(decltype(f(0))::value == 3, "");
353     }
354
355   }
356
357   namespace test_uniform_initialization
358   {
359
360     struct test
361     {
362       static const int zero {};
363       static const int one {1};
364     };
365
366     static_assert(test::zero == 0, "");
367     static_assert(test::one == 1, "");
368
369   }
370
371   namespace test_lambdas
372   {
373
374     void
375     test1()
376     {
377       auto lambda1 = [](){};
378       auto lambda2 = lambda1;
379       lambda1();
380       lambda2();
381     }
382
383     int
384     test2()
385     {
386       auto a = [](int i, int j){ return i + j; }(1, 2);
387       auto b = []() -> int { return '0'; }();
388       auto c = [=](){ return a + b; }();
389       auto d = [&](){ return c; }();
390       auto e = [a, &b](int x) mutable {
391         const auto identity = [](int y){ return y; };
392         for (auto i = 0; i < a; ++i)
393           a += b--;
394         return x + identity(a + b);
395       }(0);
396       return a + b + c + d + e;
397     }
398
399     int
400     test3()
401     {
402       const auto nullary = [](){ return 0; };
403       const auto unary = [](int x){ return x; };
404       using nullary_t = decltype(nullary);
405       using unary_t = decltype(unary);
406       const auto higher1st = [](nullary_t f){ return f(); };
407       const auto higher2nd = [unary](nullary_t f1){
408         return [unary, f1](unary_t f2){ return f2(unary(f1())); };
409       };
410       return higher1st(nullary) + higher2nd(nullary)(unary);
411     }
412
413   }
414
415   namespace test_variadic_templates
416   {
417
418     template <int...>
419     struct sum;
420
421     template <int N0, int... N1toN>
422     struct sum<N0, N1toN...>
423     {
424       static constexpr auto value = N0 + sum<N1toN...>::value;
425     };
426
427     template <>
428     struct sum<>
429     {
430       static constexpr auto value = 0;
431     };
432
433     static_assert(sum<>::value == 0, "");
434     static_assert(sum<1>::value == 1, "");
435     static_assert(sum<23>::value == 23, "");
436     static_assert(sum<1, 2>::value == 3, "");
437     static_assert(sum<5, 5, 11>::value == 21, "");
438     static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
439
440   }
441
442   // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
443   // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
444   // because of this.
445   namespace test_template_alias_sfinae
446   {
447
448     struct foo {};
449
450     template<typename T>
451     using member = typename T::member_type;
452
453     template<typename T>
454     void func(...) {}
455
456     template<typename T>
457     void func(member<T>*) {}
458
459     void test();
460
461     void test() { func<foo>(0); }
462
463   }
464
465 }  // namespace cxx11
466
467 #endif  // __cplusplus >= 201103L
468
469 ]])
470
471
472 dnl  Tests for new features in C++14
473
474 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
475
476 // If the compiler admits that it is not ready for C++14, why torture it?
477 // Hopefully, this will speed up the test.
478
479 #ifndef __cplusplus
480
481 #error "This is not a C++ compiler"
482
483 #elif __cplusplus < 201402L
484
485 #error "This is not a C++14 compiler"
486
487 #else
488
489 namespace cxx14
490 {
491
492   namespace test_polymorphic_lambdas
493   {
494
495     int
496     test()
497     {
498       const auto lambda = [](auto&&... args){
499         const auto istiny = [](auto x){
500           return (sizeof(x) == 1UL) ? 1 : 0;
501         };
502         const int aretiny[] = { istiny(args)... };
503         return aretiny[0];
504       };
505       return lambda(1, 1L, 1.0f, '1');
506     }
507
508   }
509
510   namespace test_binary_literals
511   {
512
513     constexpr auto ivii = 0b0000000000101010;
514     static_assert(ivii == 42, "wrong value");
515
516   }
517
518   namespace test_generalized_constexpr
519   {
520
521     template < typename CharT >
522     constexpr unsigned long
523     strlen_c(const CharT *const s) noexcept
524     {
525       auto length = 0UL;
526       for (auto p = s; *p; ++p)
527         ++length;
528       return length;
529     }
530
531     static_assert(strlen_c("") == 0UL, "");
532     static_assert(strlen_c("x") == 1UL, "");
533     static_assert(strlen_c("test") == 4UL, "");
534     static_assert(strlen_c("another\0test") == 7UL, "");
535
536   }
537
538   namespace test_lambda_init_capture
539   {
540
541     int
542     test()
543     {
544       auto x = 0;
545       const auto lambda1 = [a = x](int b){ return a + b; };
546       const auto lambda2 = [a = lambda1(x)](){ return a; };
547       return lambda2();
548     }
549
550   }
551
552   namespace test_digit_separators
553   {
554
555     constexpr auto ten_million = 100'000'000;
556     static_assert(ten_million == 100000000, "");
557
558   }
559
560   namespace test_return_type_deduction
561   {
562
563     auto f(int& x) { return x; }
564     decltype(auto) g(int& x) { return x; }
565
566     template < typename T1, typename T2 >
567     struct is_same
568     {
569       static constexpr auto value = false;
570     };
571
572     template < typename T >
573     struct is_same<T, T>
574     {
575       static constexpr auto value = true;
576     };
577
578     int
579     test()
580     {
581       auto x = 0;
582       static_assert(is_same<int, decltype(f(x))>::value, "");
583       static_assert(is_same<int&, decltype(g(x))>::value, "");
584       return x;
585     }
586
587   }
588
589 }  // namespace cxx14
590
591 #endif  // __cplusplus >= 201402L
592
593 ]])
594
595
596 dnl  Tests for new features in C++17
597
598 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
599
600 // If the compiler admits that it is not ready for C++17, why torture it?
601 // Hopefully, this will speed up the test.
602
603 #ifndef __cplusplus
604
605 #error "This is not a C++ compiler"
606
607 #elif __cplusplus < 201703L
608
609 #error "This is not a C++17 compiler"
610
611 #else
612
613 #include <initializer_list>
614 #include <utility>
615 #include <type_traits>
616
617 namespace cxx17
618 {
619
620   namespace test_constexpr_lambdas
621   {
622
623     constexpr int foo = [](){return 42;}();
624
625   }
626
627   namespace test::nested_namespace::definitions
628   {
629
630   }
631
632   namespace test_fold_expression
633   {
634
635     template<typename... Args>
636     int multiply(Args... args)
637     {
638       return (args * ... * 1);
639     }
640
641     template<typename... Args>
642     bool all(Args... args)
643     {
644       return (args && ...);
645     }
646
647   }
648
649   namespace test_extended_static_assert
650   {
651
652     static_assert (true);
653
654   }
655
656   namespace test_auto_brace_init_list
657   {
658
659     auto foo = {5};
660     auto bar {5};
661
662     static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
663     static_assert(std::is_same<int, decltype(bar)>::value);
664   }
665
666   namespace test_typename_in_template_template_parameter
667   {
668
669     template<template<typename> typename X> struct D;
670
671   }
672
673   namespace test_fallthrough_nodiscard_maybe_unused_attributes
674   {
675
676     int f1()
677     {
678       return 42;
679     }
680
681     [[nodiscard]] int f2()
682     {
683       [[maybe_unused]] auto unused = f1();
684
685       switch (f1())
686       {
687       case 17:
688         f1();
689         [[fallthrough]];
690       case 42:
691         f1();
692       }
693       return f1();
694     }
695
696   }
697
698   namespace test_extended_aggregate_initialization
699   {
700
701     struct base1
702     {
703       int b1, b2 = 42;
704     };
705
706     struct base2
707     {
708       base2() {
709         b3 = 42;
710       }
711       int b3;
712     };
713
714     struct derived : base1, base2
715     {
716         int d;
717     };
718
719     derived d1 {{1, 2}, {}, 4};  // full initialization
720     derived d2 {{}, {}, 4};      // value-initialized bases
721
722   }
723
724   namespace test_general_range_based_for_loop
725   {
726
727     struct iter
728     {
729       int i;
730
731       int& operator* ()
732       {
733         return i;
734       }
735
736       const int& operator* () const
737       {
738         return i;
739       }
740
741       iter& operator++()
742       {
743         ++i;
744         return *this;
745       }
746     };
747
748     struct sentinel
749     {
750       int i;
751     };
752
753     bool operator== (const iter& i, const sentinel& s)
754     {
755       return i.i == s.i;
756     }
757
758     bool operator!= (const iter& i, const sentinel& s)
759     {
760       return !(i == s);
761     }
762
763     struct range
764     {
765       iter begin() const
766       {
767         return {0};
768       }
769
770       sentinel end() const
771       {
772         return {5};
773       }
774     };
775
776     void f()
777     {
778       range r {};
779
780       for (auto i : r)
781       {
782         [[maybe_unused]] auto v = i;
783       }
784     }
785
786   }
787
788   namespace test_lambda_capture_asterisk_this_by_value
789   {
790
791     struct t
792     {
793       int i;
794       int foo()
795       {
796         return [*this]()
797         {
798           return i;
799         }();
800       }
801     };
802
803   }
804
805   namespace test_enum_class_construction
806   {
807
808     enum class byte : unsigned char
809     {};
810
811     byte foo {42};
812
813   }
814
815   namespace test_constexpr_if
816   {
817
818     template <bool cond>
819     int f ()
820     {
821       if constexpr(cond)
822       {
823         return 13;
824       }
825       else
826       {
827         return 42;
828       }
829     }
830
831   }
832
833   namespace test_selection_statement_with_initializer
834   {
835
836     int f()
837     {
838       return 13;
839     }
840
841     int f2()
842     {
843       if (auto i = f(); i > 0)
844       {
845         return 3;
846       }
847
848       switch (auto i = f(); i + 4)
849       {
850       case 17:
851         return 2;
852
853       default:
854         return 1;
855       }
856     }
857
858   }
859
860   namespace test_template_argument_deduction_for_class_templates
861   {
862
863     template <typename T1, typename T2>
864     struct pair
865     {
866       pair (T1 p1, T2 p2)
867         : m1 {p1},
868           m2 {p2}
869       {}
870
871       T1 m1;
872       T2 m2;
873     };
874
875     void f()
876     {
877       [[maybe_unused]] auto p = pair{13, 42u};
878     }
879
880   }
881
882   namespace test_non_type_auto_template_parameters
883   {
884
885     template <auto n>
886     struct B
887     {};
888
889     B<5> b1;
890     B<'a'> b2;
891
892   }
893
894   namespace test_structured_bindings
895   {
896
897     int arr[2] = { 1, 2 };
898     std::pair<int, int> pr = { 1, 2 };
899
900     auto f1() -> int(&)[2]
901     {
902       return arr;
903     }
904
905     auto f2() -> std::pair<int, int>&
906     {
907       return pr;
908     }
909
910     struct S
911     {
912       int x1 : 2;
913       volatile double y1;
914     };
915
916     S f3()
917     {
918       return {};
919     }
920
921     auto [ x1, y1 ] = f1();
922     auto& [ xr1, yr1 ] = f1();
923     auto [ x2, y2 ] = f2();
924     auto& [ xr2, yr2 ] = f2();
925     const auto [ x3, y3 ] = f3();
926
927   }
928
929   namespace test_exception_spec_type_system
930   {
931
932     struct Good {};
933     struct Bad {};
934
935     void g1() noexcept;
936     void g2();
937
938     template<typename T>
939     Bad
940     f(T*, T*);
941
942     template<typename T1, typename T2>
943     Good
944     f(T1*, T2*);
945
946     static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
947
948   }
949
950   namespace test_inline_variables
951   {
952
953     template<class T> void f(T)
954     {}
955
956     template<class T> inline T g(T)
957     {
958       return T{};
959     }
960
961     template<> inline void f<>(int)
962     {}
963
964     template<> int g<>(int)
965     {
966       return 5;
967     }
968
969   }
970
971 }  // namespace cxx17
972
973 #endif  // __cplusplus < 201703L
974
975 ]])
976
977
978 dnl  Tests for new features in C++20
979
980 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[
981
982 #ifndef __cplusplus
983
984 #error "This is not a C++ compiler"
985
986 #elif __cplusplus < 202002L
987
988 #error "This is not a C++20 compiler"
989
990 #else
991
992 #include <version>
993
994 namespace cxx20
995 {
996
997 // As C++20 supports feature test macros in the standard, there is no
998 // immediate need to actually test for feature availability on the
999 // Autoconf side.
1000
1001 }  // namespace cxx20
1002
1003 #endif  // __cplusplus < 202002L
1004
1005 ]])