1 |
schoenebeck |
3557 |
# =========================================================================== |
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 |
|
|
]]) |