xref: /freebsd/contrib/jemalloc/m4/ax_cxx_compile_stdcxx.m4 (revision 4ba91e076ee84101112d8296785098ae31dac35e)
1<<<<<<< HEAD
2# ===========================================================================
3#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
4# ===========================================================================
5#
6# SYNOPSIS
7#
8#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
9#
10# DESCRIPTION
11#
12#   Check for baseline language coverage in the compiler for the specified
13#   version of the C++ standard.  If necessary, add switches to CXX and
14#   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
15#   or '14' (for the C++14 standard).
16#
17#   The second argument, if specified, indicates whether you insist on an
18#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
19#   -std=c++11).  If neither is specified, you get whatever works, with
20#   preference for an extended mode.
21#
22#   The third argument, if specified 'mandatory' or if left unspecified,
23#   indicates that baseline support for the specified C++ standard is
24#   required and that the macro should error out if no mode with that
25#   support is found.  If specified 'optional', then configuration proceeds
26#   regardless, after defining HAVE_CXX${VERSION} if and only if a
27#   supporting mode is found.
28#
29# LICENSE
30#
31#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
32#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
33#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
34#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
35#   Copyright (c) 2015 Paul Norman <penorman@mac.com>
36#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
37#   Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
38#   Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.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 11
46
47dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
48dnl  (serial version number 13).
49
50AC_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], [noext], [], [dnl
67  if test x$ac_success = xno; then
68    for alternative in ${ax_cxx_compile_alternatives}; do
69      switch="-std=gnu++${alternative}"
70      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
71      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
72                     $cachevar,
73        [ac_save_CXX="$CXX"
74         CXX="$CXX $switch"
75         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
76          [eval $cachevar=yes],
77          [eval $cachevar=no])
78         CXX="$ac_save_CXX"])
79      if eval test x\$$cachevar = xyes; then
80        CXX="$CXX $switch"
81        if test -n "$CXXCPP" ; then
82          CXXCPP="$CXXCPP $switch"
83        fi
84        ac_success=yes
85        break
86      fi
87    done
88  fi])
89
90  m4_if([$2], [ext], [], [dnl
91  if test x$ac_success = xno; then
92    dnl HP's aCC needs +std=c++11 according to:
93    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
94    dnl Cray's crayCC needs "-h std=c++11"
95    for alternative in ${ax_cxx_compile_alternatives}; do
96      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
97        cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
98        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
99                       $cachevar,
100          [ac_save_CXX="$CXX"
101           CXX="$CXX $switch"
102           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
103            [eval $cachevar=yes],
104            [eval $cachevar=no])
105           CXX="$ac_save_CXX"])
106        if eval test x\$$cachevar = xyes; then
107          CXX="$CXX $switch"
108          if test -n "$CXXCPP" ; then
109            CXXCPP="$CXXCPP $switch"
110          fi
111          ac_success=yes
112          break
113        fi
114      done
115      if test x$ac_success = xyes; then
116        break
117      fi
118    done
119  fi])
120  AC_LANG_POP([C++])
121  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
122    if test x$ac_success = xno; then
123      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
124    fi
125  fi
126  if test x$ac_success = xno; then
127    HAVE_CXX$1=0
128    AC_MSG_NOTICE([No compiler with C++$1 support was found])
129  else
130    HAVE_CXX$1=1
131    AC_DEFINE(HAVE_CXX$1,1,
132              [define if the compiler supports basic C++$1 syntax])
133  fi
134  AC_SUBST(HAVE_CXX$1)
135])
136
137
138dnl  Test body for checking C++11 support
139
140m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
141  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
142)
143
144
145dnl  Test body for checking C++14 support
146
147m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
148  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
149  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
150)
151
152m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
153  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
154  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
155  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
156)
157
158dnl  Tests for new features in C++11
159
160m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
161
162// If the compiler admits that it is not ready for C++11, why torture it?
163// Hopefully, this will speed up the test.
164
165#ifndef __cplusplus
166
167#error "This is not a C++ compiler"
168
169#elif __cplusplus < 201103L
170
171#error "This is not a C++11 compiler"
172
173#else
174
175namespace cxx11
176{
177
178  namespace test_static_assert
179  {
180
181    template <typename T>
182    struct check
183    {
184      static_assert(sizeof(int) <= sizeof(T), "not big enough");
185    };
186
187  }
188
189  namespace test_final_override
190  {
191
192    struct Base
193    {
194      virtual ~Base() {}
195      virtual void f() {}
196    };
197
198    struct Derived : public Base
199    {
200      virtual ~Derived() override {}
201      virtual void f() override {}
202    };
203
204  }
205
206  namespace test_double_right_angle_brackets
207  {
208
209    template < typename T >
210    struct check {};
211
212    typedef check<void> single_type;
213    typedef check<check<void>> double_type;
214    typedef check<check<check<void>>> triple_type;
215    typedef check<check<check<check<void>>>> quadruple_type;
216
217  }
218
219  namespace test_decltype
220  {
221
222    int
223    f()
224    {
225      int a = 1;
226      decltype(a) b = 2;
227      return a + b;
228    }
229
230  }
231
232  namespace test_type_deduction
233  {
234
235    template < typename T1, typename T2 >
236    struct is_same
237    {
238      static const bool value = false;
239    };
240
241    template < typename T >
242    struct is_same<T, T>
243    {
244      static const bool value = true;
245    };
246
247    template < typename T1, typename T2 >
248    auto
249    add(T1 a1, T2 a2) -> decltype(a1 + a2)
250    {
251      return a1 + a2;
252    }
253
254    int
255    test(const int c, volatile int v)
256    {
257      static_assert(is_same<int, decltype(0)>::value == true, "");
258      static_assert(is_same<int, decltype(c)>::value == false, "");
259      static_assert(is_same<int, decltype(v)>::value == false, "");
260      auto ac = c;
261      auto av = v;
262      auto sumi = ac + av + 'x';
263      auto sumf = ac + av + 1.0;
264      static_assert(is_same<int, decltype(ac)>::value == true, "");
265      static_assert(is_same<int, decltype(av)>::value == true, "");
266      static_assert(is_same<int, decltype(sumi)>::value == true, "");
267      static_assert(is_same<int, decltype(sumf)>::value == false, "");
268      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
269      return (sumf > 0.0) ? sumi : add(c, v);
270    }
271
272  }
273
274  namespace test_noexcept
275  {
276
277    int f() { return 0; }
278    int g() noexcept { return 0; }
279
280    static_assert(noexcept(f()) == false, "");
281    static_assert(noexcept(g()) == true, "");
282
283  }
284
285  namespace test_constexpr
286  {
287
288    template < typename CharT >
289    unsigned long constexpr
290    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
291    {
292      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
293    }
294
295    template < typename CharT >
296    unsigned long constexpr
297    strlen_c(const CharT *const s) noexcept
298    {
299      return strlen_c_r(s, 0UL);
300    }
301
302    static_assert(strlen_c("") == 0UL, "");
303    static_assert(strlen_c("1") == 1UL, "");
304    static_assert(strlen_c("example") == 7UL, "");
305    static_assert(strlen_c("another\0example") == 7UL, "");
306
307  }
308
309  namespace test_rvalue_references
310  {
311
312    template < int N >
313    struct answer
314    {
315      static constexpr int value = N;
316    };
317
318    answer<1> f(int&)       { return answer<1>(); }
319    answer<2> f(const int&) { return answer<2>(); }
320    answer<3> f(int&&)      { return answer<3>(); }
321
322    void
323    test()
324    {
325      int i = 0;
326      const int c = 0;
327      static_assert(decltype(f(i))::value == 1, "");
328      static_assert(decltype(f(c))::value == 2, "");
329      static_assert(decltype(f(0))::value == 3, "");
330    }
331
332  }
333
334  namespace test_uniform_initialization
335  {
336
337    struct test
338    {
339      static const int zero {};
340      static const int one {1};
341    };
342
343    static_assert(test::zero == 0, "");
344    static_assert(test::one == 1, "");
345
346  }
347
348  namespace test_lambdas
349  {
350
351    void
352    test1()
353    {
354      auto lambda1 = [](){};
355      auto lambda2 = lambda1;
356      lambda1();
357      lambda2();
358    }
359
360    int
361    test2()
362    {
363      auto a = [](int i, int j){ return i + j; }(1, 2);
364      auto b = []() -> int { return '0'; }();
365      auto c = [=](){ return a + b; }();
366      auto d = [&](){ return c; }();
367      auto e = [a, &b](int x) mutable {
368        const auto identity = [](int y){ return y; };
369        for (auto i = 0; i < a; ++i)
370          a += b--;
371        return x + identity(a + b);
372      }(0);
373      return a + b + c + d + e;
374    }
375
376    int
377    test3()
378    {
379      const auto nullary = [](){ return 0; };
380      const auto unary = [](int x){ return x; };
381      using nullary_t = decltype(nullary);
382      using unary_t = decltype(unary);
383      const auto higher1st = [](nullary_t f){ return f(); };
384      const auto higher2nd = [unary](nullary_t f1){
385        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
386      };
387      return higher1st(nullary) + higher2nd(nullary)(unary);
388    }
389
390  }
391
392  namespace test_variadic_templates
393  {
394
395    template <int...>
396    struct sum;
397
398    template <int N0, int... N1toN>
399    struct sum<N0, N1toN...>
400    {
401      static constexpr auto value = N0 + sum<N1toN...>::value;
402    };
403
404    template <>
405    struct sum<>
406    {
407      static constexpr auto value = 0;
408    };
409
410    static_assert(sum<>::value == 0, "");
411    static_assert(sum<1>::value == 1, "");
412    static_assert(sum<23>::value == 23, "");
413    static_assert(sum<1, 2>::value == 3, "");
414    static_assert(sum<5, 5, 11>::value == 21, "");
415    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
416
417  }
418
419  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
420  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
421  // because of this.
422  namespace test_template_alias_sfinae
423  {
424
425    struct foo {};
426
427    template<typename T>
428    using member = typename T::member_type;
429
430    template<typename T>
431    void func(...) {}
432
433    template<typename T>
434    void func(member<T>*) {}
435
436    void test();
437
438    void test() { func<foo>(0); }
439
440  }
441
442}  // namespace cxx11
443
444#endif  // __cplusplus >= 201103L
445
446]])
447
448
449dnl  Tests for new features in C++14
450
451m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
452
453// If the compiler admits that it is not ready for C++14, why torture it?
454// Hopefully, this will speed up the test.
455
456#ifndef __cplusplus
457
458#error "This is not a C++ compiler"
459
460#elif __cplusplus < 201402L
461
462#error "This is not a C++14 compiler"
463
464#else
465
466namespace cxx14
467{
468
469  namespace test_polymorphic_lambdas
470  {
471
472    int
473    test()
474    {
475      const auto lambda = [](auto&&... args){
476        const auto istiny = [](auto x){
477          return (sizeof(x) == 1UL) ? 1 : 0;
478        };
479        const int aretiny[] = { istiny(args)... };
480        return aretiny[0];
481      };
482      return lambda(1, 1L, 1.0f, '1');
483    }
484
485  }
486
487  namespace test_binary_literals
488  {
489
490    constexpr auto ivii = 0b0000000000101010;
491    static_assert(ivii == 42, "wrong value");
492
493  }
494
495  namespace test_generalized_constexpr
496  {
497
498    template < typename CharT >
499    constexpr unsigned long
500    strlen_c(const CharT *const s) noexcept
501    {
502      auto length = 0UL;
503      for (auto p = s; *p; ++p)
504        ++length;
505      return length;
506    }
507
508    static_assert(strlen_c("") == 0UL, "");
509    static_assert(strlen_c("x") == 1UL, "");
510    static_assert(strlen_c("test") == 4UL, "");
511    static_assert(strlen_c("another\0test") == 7UL, "");
512
513  }
514
515  namespace test_lambda_init_capture
516  {
517
518    int
519    test()
520    {
521      auto x = 0;
522      const auto lambda1 = [a = x](int b){ return a + b; };
523      const auto lambda2 = [a = lambda1(x)](){ return a; };
524      return lambda2();
525    }
526
527  }
528
529  namespace test_digit_separators
530  {
531
532    constexpr auto ten_million = 100'000'000;
533    static_assert(ten_million == 100000000, "");
534
535  }
536
537  namespace test_return_type_deduction
538  {
539
540    auto f(int& x) { return x; }
541    decltype(auto) g(int& x) { return x; }
542
543    template < typename T1, typename T2 >
544    struct is_same
545    {
546      static constexpr auto value = false;
547    };
548
549    template < typename T >
550    struct is_same<T, T>
551    {
552      static constexpr auto value = true;
553    };
554
555    int
556    test()
557    {
558      auto x = 0;
559      static_assert(is_same<int, decltype(f(x))>::value, "");
560      static_assert(is_same<int&, decltype(g(x))>::value, "");
561      return x;
562    }
563
564  }
565
566}  // namespace cxx14
567
568#endif  // __cplusplus >= 201402L
569
570]])
571
572
573dnl  Tests for new features in C++17
574
575m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
576
577// If the compiler admits that it is not ready for C++17, why torture it?
578// Hopefully, this will speed up the test.
579
580#ifndef __cplusplus
581
582#error "This is not a C++ compiler"
583
584#elif __cplusplus < 201703L
585
586#error "This is not a C++17 compiler"
587
588#else
589
590#include <initializer_list>
591#include <utility>
592#include <type_traits>
593
594namespace cxx17
595{
596
597  namespace test_constexpr_lambdas
598  {
599
600    constexpr int foo = [](){return 42;}();
601
602  }
603
604  namespace test::nested_namespace::definitions
605  {
606
607  }
608
609  namespace test_fold_expression
610  {
611
612    template<typename... Args>
613    int multiply(Args... args)
614    {
615      return (args * ... * 1);
616    }
617
618    template<typename... Args>
619    bool all(Args... args)
620    {
621      return (args && ...);
622    }
623
624  }
625
626  namespace test_extended_static_assert
627  {
628
629    static_assert (true);
630
631  }
632
633  namespace test_auto_brace_init_list
634  {
635
636    auto foo = {5};
637    auto bar {5};
638
639    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
640    static_assert(std::is_same<int, decltype(bar)>::value);
641  }
642
643  namespace test_typename_in_template_template_parameter
644  {
645
646    template<template<typename> typename X> struct D;
647
648  }
649
650  namespace test_fallthrough_nodiscard_maybe_unused_attributes
651  {
652
653    int f1()
654    {
655      return 42;
656    }
657
658    [[nodiscard]] int f2()
659    {
660      [[maybe_unused]] auto unused = f1();
661
662      switch (f1())
663      {
664      case 17:
665        f1();
666        [[fallthrough]];
667      case 42:
668        f1();
669      }
670      return f1();
671    }
672
673  }
674
675  namespace test_extended_aggregate_initialization
676  {
677
678    struct base1
679    {
680      int b1, b2 = 42;
681    };
682
683    struct base2
684    {
685      base2() {
686        b3 = 42;
687      }
688      int b3;
689    };
690
691    struct derived : base1, base2
692    {
693        int d;
694    };
695
696    derived d1 {{1, 2}, {}, 4};  // full initialization
697    derived d2 {{}, {}, 4};      // value-initialized bases
698
699  }
700
701  namespace test_general_range_based_for_loop
702  {
703
704    struct iter
705    {
706      int i;
707
708      int& operator* ()
709      {
710        return i;
711      }
712
713      const int& operator* () const
714      {
715        return i;
716      }
717
718      iter& operator++()
719      {
720        ++i;
721        return *this;
722      }
723    };
724
725    struct sentinel
726    {
727      int i;
728    };
729
730    bool operator== (const iter& i, const sentinel& s)
731    {
732      return i.i == s.i;
733    }
734
735    bool operator!= (const iter& i, const sentinel& s)
736    {
737      return !(i == s);
738    }
739
740    struct range
741    {
742      iter begin() const
743      {
744        return {0};
745      }
746
747      sentinel end() const
748      {
749        return {5};
750      }
751    };
752
753    void f()
754    {
755      range r {};
756
757      for (auto i : r)
758      {
759        [[maybe_unused]] auto v = i;
760      }
761    }
762
763  }
764
765  namespace test_lambda_capture_asterisk_this_by_value
766  {
767
768    struct t
769    {
770      int i;
771      int foo()
772      {
773        return [*this]()
774        {
775          return i;
776        }();
777      }
778    };
779
780  }
781
782  namespace test_enum_class_construction
783  {
784
785    enum class byte : unsigned char
786    {};
787
788    byte foo {42};
789
790  }
791
792  namespace test_constexpr_if
793  {
794
795    template <bool cond>
796    int f ()
797    {
798      if constexpr(cond)
799      {
800        return 13;
801      }
802      else
803      {
804        return 42;
805      }
806    }
807
808  }
809
810  namespace test_selection_statement_with_initializer
811  {
812
813    int f()
814    {
815      return 13;
816    }
817
818    int f2()
819    {
820      if (auto i = f(); i > 0)
821      {
822        return 3;
823      }
824
825      switch (auto i = f(); i + 4)
826      {
827      case 17:
828        return 2;
829
830      default:
831        return 1;
832      }
833    }
834
835  }
836
837  namespace test_template_argument_deduction_for_class_templates
838  {
839
840    template <typename T1, typename T2>
841    struct pair
842    {
843      pair (T1 p1, T2 p2)
844        : m1 {p1},
845          m2 {p2}
846      {}
847
848      T1 m1;
849      T2 m2;
850    };
851
852    void f()
853    {
854      [[maybe_unused]] auto p = pair{13, 42u};
855    }
856
857  }
858
859  namespace test_non_type_auto_template_parameters
860  {
861
862    template <auto n>
863    struct B
864    {};
865
866    B<5> b1;
867    B<'a'> b2;
868
869  }
870
871  namespace test_structured_bindings
872  {
873
874    int arr[2] = { 1, 2 };
875    std::pair<int, int> pr = { 1, 2 };
876
877    auto f1() -> int(&)[2]
878    {
879      return arr;
880    }
881
882    auto f2() -> std::pair<int, int>&
883    {
884      return pr;
885    }
886
887    struct S
888    {
889      int x1 : 2;
890      volatile double y1;
891    };
892
893    S f3()
894    {
895      return {};
896    }
897
898    auto [ x1, y1 ] = f1();
899    auto& [ xr1, yr1 ] = f1();
900    auto [ x2, y2 ] = f2();
901    auto& [ xr2, yr2 ] = f2();
902    const auto [ x3, y3 ] = f3();
903
904  }
905
906  namespace test_exception_spec_type_system
907  {
908
909    struct Good {};
910    struct Bad {};
911
912    void g1() noexcept;
913    void g2();
914
915    template<typename T>
916    Bad
917    f(T*, T*);
918
919    template<typename T1, typename T2>
920    Good
921    f(T1*, T2*);
922
923    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
924
925  }
926
927  namespace test_inline_variables
928  {
929
930    template<class T> void f(T)
931    {}
932
933    template<class T> inline T g(T)
934    {
935      return T{};
936    }
937
938    template<> inline void f<>(int)
939    {}
940
941    template<> int g<>(int)
942    {
943      return 5;
944    }
945
946  }
947
948}  // namespace cxx17
949
950#endif  // __cplusplus < 201703L
951
952]])
953||||||| dec341af7695
954=======
955# ===========================================================================
956#   http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
957# ===========================================================================
958#
959# SYNOPSIS
960#
961#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
962#
963# DESCRIPTION
964#
965#   Check for baseline language coverage in the compiler for the specified
966#   version of the C++ standard.  If necessary, add switches to CXX and
967#   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
968#   or '14' (for the C++14 standard).
969#
970#   The second argument, if specified, indicates whether you insist on an
971#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
972#   -std=c++11).  If neither is specified, you get whatever works, with
973#   preference for an extended mode.
974#
975#   The third argument, if specified 'mandatory' or if left unspecified,
976#   indicates that baseline support for the specified C++ standard is
977#   required and that the macro should error out if no mode with that
978#   support is found.  If specified 'optional', then configuration proceeds
979#   regardless, after defining HAVE_CXX${VERSION} if and only if a
980#   supporting mode is found.
981#
982# LICENSE
983#
984#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
985#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
986#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
987#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
988#   Copyright (c) 2015 Paul Norman <penorman@mac.com>
989#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
990#
991#   Copying and distribution of this file, with or without modification, are
992#   permitted in any medium without royalty provided the copyright notice
993#   and this notice are preserved.  This file is offered as-is, without any
994#   warranty.
995
996#serial 4
997
998dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
999dnl  (serial version number 13).
1000
1001AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
1002  m4_if([$1], [11], [],
1003        [$1], [14], [],
1004        [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
1005        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
1006  m4_if([$2], [], [],
1007        [$2], [ext], [],
1008        [$2], [noext], [],
1009        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
1010  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
1011        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
1012        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
1013        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
1014  AC_LANG_PUSH([C++])dnl
1015  ac_success=no
1016  AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
1017  ax_cv_cxx_compile_cxx$1,
1018  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
1019    [ax_cv_cxx_compile_cxx$1=yes],
1020    [ax_cv_cxx_compile_cxx$1=no])])
1021  if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
1022    ac_success=yes
1023  fi
1024
1025  m4_if([$2], [noext], [], [dnl
1026  if test x$ac_success = xno; then
1027    for switch in -std=gnu++$1 -std=gnu++0x; do
1028      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
1029      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
1030                     $cachevar,
1031        [ac_save_CXX="$CXX"
1032         CXX="$CXX $switch"
1033         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
1034          [eval $cachevar=yes],
1035          [eval $cachevar=no])
1036         CXX="$ac_save_CXX"])
1037      if eval test x\$$cachevar = xyes; then
1038        CXX="$CXX $switch"
1039        if test -n "$CXXCPP" ; then
1040          CXXCPP="$CXXCPP $switch"
1041        fi
1042        ac_success=yes
1043        break
1044      fi
1045    done
1046  fi])
1047
1048  m4_if([$2], [ext], [], [dnl
1049  if test x$ac_success = xno; then
1050    dnl HP's aCC needs +std=c++11 according to:
1051    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
1052    dnl Cray's crayCC needs "-h std=c++11"
1053    for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
1054      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
1055      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
1056                     $cachevar,
1057        [ac_save_CXX="$CXX"
1058         CXX="$CXX $switch"
1059         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
1060          [eval $cachevar=yes],
1061          [eval $cachevar=no])
1062         CXX="$ac_save_CXX"])
1063      if eval test x\$$cachevar = xyes; then
1064        CXX="$CXX $switch"
1065        if test -n "$CXXCPP" ; then
1066          CXXCPP="$CXXCPP $switch"
1067        fi
1068        ac_success=yes
1069        break
1070      fi
1071    done
1072  fi])
1073  AC_LANG_POP([C++])
1074  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
1075    if test x$ac_success = xno; then
1076      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
1077    fi
1078  fi
1079  if test x$ac_success = xno; then
1080    HAVE_CXX$1=0
1081    AC_MSG_NOTICE([No compiler with C++$1 support was found])
1082  else
1083    HAVE_CXX$1=1
1084    AC_DEFINE(HAVE_CXX$1,1,
1085              [define if the compiler supports basic C++$1 syntax])
1086  fi
1087  AC_SUBST(HAVE_CXX$1)
1088])
1089
1090
1091dnl  Test body for checking C++11 support
1092
1093m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
1094  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
1095)
1096
1097
1098dnl  Test body for checking C++14 support
1099
1100m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
1101  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
1102  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
1103)
1104
1105
1106dnl  Tests for new features in C++11
1107
1108m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
1109
1110// If the compiler admits that it is not ready for C++11, why torture it?
1111// Hopefully, this will speed up the test.
1112
1113#ifndef __cplusplus
1114
1115#error "This is not a C++ compiler"
1116
1117#elif __cplusplus < 201103L
1118
1119#error "This is not a C++11 compiler"
1120
1121#else
1122
1123namespace cxx11
1124{
1125
1126  namespace test_static_assert
1127  {
1128
1129    template <typename T>
1130    struct check
1131    {
1132      static_assert(sizeof(int) <= sizeof(T), "not big enough");
1133    };
1134
1135  }
1136
1137  namespace test_final_override
1138  {
1139
1140    struct Base
1141    {
1142      virtual void f() {}
1143    };
1144
1145    struct Derived : public Base
1146    {
1147      virtual void f() override {}
1148    };
1149
1150  }
1151
1152  namespace test_double_right_angle_brackets
1153  {
1154
1155    template < typename T >
1156    struct check {};
1157
1158    typedef check<void> single_type;
1159    typedef check<check<void>> double_type;
1160    typedef check<check<check<void>>> triple_type;
1161    typedef check<check<check<check<void>>>> quadruple_type;
1162
1163  }
1164
1165  namespace test_decltype
1166  {
1167
1168    int
1169    f()
1170    {
1171      int a = 1;
1172      decltype(a) b = 2;
1173      return a + b;
1174    }
1175
1176  }
1177
1178  namespace test_type_deduction
1179  {
1180
1181    template < typename T1, typename T2 >
1182    struct is_same
1183    {
1184      static const bool value = false;
1185    };
1186
1187    template < typename T >
1188    struct is_same<T, T>
1189    {
1190      static const bool value = true;
1191    };
1192
1193    template < typename T1, typename T2 >
1194    auto
1195    add(T1 a1, T2 a2) -> decltype(a1 + a2)
1196    {
1197      return a1 + a2;
1198    }
1199
1200    int
1201    test(const int c, volatile int v)
1202    {
1203      static_assert(is_same<int, decltype(0)>::value == true, "");
1204      static_assert(is_same<int, decltype(c)>::value == false, "");
1205      static_assert(is_same<int, decltype(v)>::value == false, "");
1206      auto ac = c;
1207      auto av = v;
1208      auto sumi = ac + av + 'x';
1209      auto sumf = ac + av + 1.0;
1210      static_assert(is_same<int, decltype(ac)>::value == true, "");
1211      static_assert(is_same<int, decltype(av)>::value == true, "");
1212      static_assert(is_same<int, decltype(sumi)>::value == true, "");
1213      static_assert(is_same<int, decltype(sumf)>::value == false, "");
1214      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
1215      return (sumf > 0.0) ? sumi : add(c, v);
1216    }
1217
1218  }
1219
1220  namespace test_noexcept
1221  {
1222
1223    int f() { return 0; }
1224    int g() noexcept { return 0; }
1225
1226    static_assert(noexcept(f()) == false, "");
1227    static_assert(noexcept(g()) == true, "");
1228
1229  }
1230
1231  namespace test_constexpr
1232  {
1233
1234    template < typename CharT >
1235    unsigned long constexpr
1236    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
1237    {
1238      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
1239    }
1240
1241    template < typename CharT >
1242    unsigned long constexpr
1243    strlen_c(const CharT *const s) noexcept
1244    {
1245      return strlen_c_r(s, 0UL);
1246    }
1247
1248    static_assert(strlen_c("") == 0UL, "");
1249    static_assert(strlen_c("1") == 1UL, "");
1250    static_assert(strlen_c("example") == 7UL, "");
1251    static_assert(strlen_c("another\0example") == 7UL, "");
1252
1253  }
1254
1255  namespace test_rvalue_references
1256  {
1257
1258    template < int N >
1259    struct answer
1260    {
1261      static constexpr int value = N;
1262    };
1263
1264    answer<1> f(int&)       { return answer<1>(); }
1265    answer<2> f(const int&) { return answer<2>(); }
1266    answer<3> f(int&&)      { return answer<3>(); }
1267
1268    void
1269    test()
1270    {
1271      int i = 0;
1272      const int c = 0;
1273      static_assert(decltype(f(i))::value == 1, "");
1274      static_assert(decltype(f(c))::value == 2, "");
1275      static_assert(decltype(f(0))::value == 3, "");
1276    }
1277
1278  }
1279
1280  namespace test_uniform_initialization
1281  {
1282
1283    struct test
1284    {
1285      static const int zero {};
1286      static const int one {1};
1287    };
1288
1289    static_assert(test::zero == 0, "");
1290    static_assert(test::one == 1, "");
1291
1292  }
1293
1294  namespace test_lambdas
1295  {
1296
1297    void
1298    test1()
1299    {
1300      auto lambda1 = [](){};
1301      auto lambda2 = lambda1;
1302      lambda1();
1303      lambda2();
1304    }
1305
1306    int
1307    test2()
1308    {
1309      auto a = [](int i, int j){ return i + j; }(1, 2);
1310      auto b = []() -> int { return '0'; }();
1311      auto c = [=](){ return a + b; }();
1312      auto d = [&](){ return c; }();
1313      auto e = [a, &b](int x) mutable {
1314        const auto identity = [](int y){ return y; };
1315        for (auto i = 0; i < a; ++i)
1316          a += b--;
1317        return x + identity(a + b);
1318      }(0);
1319      return a + b + c + d + e;
1320    }
1321
1322    int
1323    test3()
1324    {
1325      const auto nullary = [](){ return 0; };
1326      const auto unary = [](int x){ return x; };
1327      using nullary_t = decltype(nullary);
1328      using unary_t = decltype(unary);
1329      const auto higher1st = [](nullary_t f){ return f(); };
1330      const auto higher2nd = [unary](nullary_t f1){
1331        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
1332      };
1333      return higher1st(nullary) + higher2nd(nullary)(unary);
1334    }
1335
1336  }
1337
1338  namespace test_variadic_templates
1339  {
1340
1341    template <int...>
1342    struct sum;
1343
1344    template <int N0, int... N1toN>
1345    struct sum<N0, N1toN...>
1346    {
1347      static constexpr auto value = N0 + sum<N1toN...>::value;
1348    };
1349
1350    template <>
1351    struct sum<>
1352    {
1353      static constexpr auto value = 0;
1354    };
1355
1356    static_assert(sum<>::value == 0, "");
1357    static_assert(sum<1>::value == 1, "");
1358    static_assert(sum<23>::value == 23, "");
1359    static_assert(sum<1, 2>::value == 3, "");
1360    static_assert(sum<5, 5, 11>::value == 21, "");
1361    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
1362
1363  }
1364
1365  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
1366  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
1367  // because of this.
1368  namespace test_template_alias_sfinae
1369  {
1370
1371    struct foo {};
1372
1373    template<typename T>
1374    using member = typename T::member_type;
1375
1376    template<typename T>
1377    void func(...) {}
1378
1379    template<typename T>
1380    void func(member<T>*) {}
1381
1382    void test();
1383
1384    void test() { func<foo>(0); }
1385
1386  }
1387
1388}  // namespace cxx11
1389
1390#endif  // __cplusplus >= 201103L
1391
1392]])
1393
1394
1395dnl  Tests for new features in C++14
1396
1397m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
1398
1399// If the compiler admits that it is not ready for C++14, why torture it?
1400// Hopefully, this will speed up the test.
1401
1402#ifndef __cplusplus
1403
1404#error "This is not a C++ compiler"
1405
1406#elif __cplusplus < 201402L
1407
1408#error "This is not a C++14 compiler"
1409
1410#else
1411
1412namespace cxx14
1413{
1414
1415  namespace test_polymorphic_lambdas
1416  {
1417
1418    int
1419    test()
1420    {
1421      const auto lambda = [](auto&&... args){
1422        const auto istiny = [](auto x){
1423          return (sizeof(x) == 1UL) ? 1 : 0;
1424        };
1425        const int aretiny[] = { istiny(args)... };
1426        return aretiny[0];
1427      };
1428      return lambda(1, 1L, 1.0f, '1');
1429    }
1430
1431  }
1432
1433  namespace test_binary_literals
1434  {
1435
1436    constexpr auto ivii = 0b0000000000101010;
1437    static_assert(ivii == 42, "wrong value");
1438
1439  }
1440
1441  namespace test_generalized_constexpr
1442  {
1443
1444    template < typename CharT >
1445    constexpr unsigned long
1446    strlen_c(const CharT *const s) noexcept
1447    {
1448      auto length = 0UL;
1449      for (auto p = s; *p; ++p)
1450        ++length;
1451      return length;
1452    }
1453
1454    static_assert(strlen_c("") == 0UL, "");
1455    static_assert(strlen_c("x") == 1UL, "");
1456    static_assert(strlen_c("test") == 4UL, "");
1457    static_assert(strlen_c("another\0test") == 7UL, "");
1458
1459  }
1460
1461  namespace test_lambda_init_capture
1462  {
1463
1464    int
1465    test()
1466    {
1467      auto x = 0;
1468      const auto lambda1 = [a = x](int b){ return a + b; };
1469      const auto lambda2 = [a = lambda1(x)](){ return a; };
1470      return lambda2();
1471    }
1472
1473  }
1474
1475  namespace test_digit_seperators
1476  {
1477
1478    constexpr auto ten_million = 100'000'000;
1479    static_assert(ten_million == 100000000, "");
1480
1481  }
1482
1483  namespace test_return_type_deduction
1484  {
1485
1486    auto f(int& x) { return x; }
1487    decltype(auto) g(int& x) { return x; }
1488
1489    template < typename T1, typename T2 >
1490    struct is_same
1491    {
1492      static constexpr auto value = false;
1493    };
1494
1495    template < typename T >
1496    struct is_same<T, T>
1497    {
1498      static constexpr auto value = true;
1499    };
1500
1501    int
1502    test()
1503    {
1504      auto x = 0;
1505      static_assert(is_same<int, decltype(f(x))>::value, "");
1506      static_assert(is_same<int&, decltype(g(x))>::value, "");
1507      return x;
1508    }
1509
1510  }
1511
1512}  // namespace cxx14
1513
1514#endif  // __cplusplus >= 201402L
1515
1516]])
1517>>>>>>> main
1518