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