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