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