1dnl ---------------------------------------------------------------- 2dnl Tests for various C++11 features. These will probably only work 3dnl if they are run after the autoconf test that sets -std=c++11. 4dnl ---------------------------------------------------------------- 5 6dnl Test C++11 std::isnan, std::isinf 7AC_DEFUN([LIBMESH_TEST_CXX11_ISNAN_ISINF], 8 [ 9 have_cxx11_isnan=no 10 have_cxx11_isinf=no 11 12 AC_LANG_PUSH([C++]) 13 14 old_CXXFLAGS="$CXXFLAGS" 15 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 16 17 AC_MSG_CHECKING(for C++11 std::isnan) 18 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 19 @%:@include <cmath> 20 ]], [[ 21 if (std::isnan(0.0)) 22 return 1; 23 ]])],[ 24 AC_MSG_RESULT(yes) 25 have_cxx11_isnan=yes 26 dnl AC_DEFINE(HAVE_CXX11_ISNAN, 1, [Flag indicating whether compiler supports std::isnan]) 27 ],[ 28 AC_MSG_RESULT(no) 29 ]) 30 31 AC_MSG_CHECKING(for C++11 std::isinf) 32 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 33 @%:@include <cmath> 34 ]], [[ 35 if (std::isinf(0.0)) 36 return 1; 37 ]])],[ 38 AC_MSG_RESULT(yes) 39 have_cxx11_isinf=yes 40 dnl AC_DEFINE(HAVE_CXX11_ISINF, 1, [Flag indicating whether compiler supports std::isinf]) 41 ],[ 42 AC_MSG_RESULT(no) 43 ]) 44 45 dnl Reset the flags 46 CXXFLAGS="$old_CXXFLAGS" 47 AC_LANG_POP([C++]) 48 ]) 49 50dnl Test C++11 std::array 51AC_DEFUN([LIBMESH_TEST_CXX11_ARRAY], 52 [ 53 have_cxx11_array=no 54 55 AC_MSG_CHECKING(for C++11 std::array) 56 AC_LANG_PUSH([C++]) 57 58 old_CXXFLAGS="$CXXFLAGS" 59 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 60 61 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 62 @%:@include <array> 63 ]], [[ 64 std::array<double, 4> a; 65 a[0] = 42.0; 66 double * begin = a.data(); 67 ]])],[ 68 AC_MSG_RESULT(yes) 69 have_cxx11_array=yes 70 ],[ 71 AC_MSG_RESULT(no) 72 ]) 73 74 dnl Reset the flags 75 CXXFLAGS="$old_CXXFLAGS" 76 AC_LANG_POP([C++]) 77 ]) 78 79dnl Test C++11 std::vector::data() 80AC_DEFUN([LIBMESH_TEST_CXX11_VECTOR_DATA], 81 [ 82 have_cxx11_vector_data=no 83 84 AC_MSG_CHECKING(for C++11 std::vector::data() API) 85 AC_LANG_PUSH([C++]) 86 87 old_CXXFLAGS="$CXXFLAGS" 88 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 89 90 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 91 @%:@include <vector> 92 ]], [[ 93 std::vector<int> v(10); 94 int * begin = v.data(); 95 ]])],[ 96 AC_MSG_RESULT(yes) 97 have_cxx11_vector_data=yes 98 ],[ 99 AC_MSG_RESULT(no) 100 ]) 101 102 dnl Reset the flags 103 CXXFLAGS="$old_CXXFLAGS" 104 AC_LANG_POP([C++]) 105 ]) 106 107dnl Test C++11 std::iota 108AC_DEFUN([LIBMESH_TEST_CXX11_IOTA], 109 [ 110 have_cxx11_iota=no 111 112 AC_MSG_CHECKING(for C++11 std::iota algorithm) 113 AC_LANG_PUSH([C++]) 114 115 old_CXXFLAGS="$CXXFLAGS" 116 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 117 118 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 119 @%:@include <vector> 120 @%:@include <numeric> 121 ]], [[ 122 std::vector<int> v(10); 123 std::iota(v.begin(), v.end(), 0); 124 ]])],[ 125 AC_MSG_RESULT(yes) 126 have_cxx11_iota=yes 127 ],[ 128 AC_MSG_RESULT(no) 129 ]) 130 131 dnl Reset the flags 132 CXXFLAGS="$old_CXXFLAGS" 133 AC_LANG_POP([C++]) 134 ]) 135 136dnl Test C++11 std::map,set,multimap,multiset iterator-returning erase() APIs. 137AC_DEFUN([LIBMESH_TEST_CXX11_CONTAINER_ERASE], 138 [ 139 have_cxx11_container_erase=no 140 141 AC_MSG_CHECKING(for C++11 std container erase() functions returning iterators) 142 AC_LANG_PUSH([C++]) 143 144 old_CXXFLAGS="$CXXFLAGS" 145 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 146 147 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 148 @%:@include <map> 149 @%:@include <set> 150 ]], [[ 151 { 152 std::map<int, int> m; 153 m.insert(std::make_pair(1,2)); 154 std::map<int, int>::iterator it = m.erase(m.begin()); 155 } 156 { 157 std::set<int> s; 158 s.insert(1); 159 std::set<int>::iterator it = s.erase(s.begin()); 160 } 161 { 162 std::multimap<int, int> m; 163 m.insert(std::make_pair(1,2)); 164 std::multimap<int, int>::iterator it = m.erase(m.begin()); 165 } 166 { 167 std::multiset<int> s; 168 s.insert(1); 169 std::multiset<int>::iterator it = s.erase(s.begin()); 170 } 171 ]])],[ 172 AC_MSG_RESULT(yes) 173 have_cxx11_container_erase=yes 174 ],[ 175 AC_MSG_RESULT(no) 176 ]) 177 178 dnl Reset the flags 179 CXXFLAGS="$old_CXXFLAGS" 180 AC_LANG_POP([C++]) 181 ]) 182 183dnl Test C++11 std::map,set,multimap,multiset emplace APIs. 184AC_DEFUN([LIBMESH_TEST_CXX11_CONTAINER_EMPLACE], 185 [ 186 have_cxx11_container_emplace=no 187 188 AC_MSG_CHECKING(for C++11 std container emplace() functions) 189 AC_LANG_PUSH([C++]) 190 191 old_CXXFLAGS="$CXXFLAGS" 192 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 193 194 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 195 @%:@include <map> 196 @%:@include <set> 197 @%:@include <vector> 198 ]], [[ 199 { 200 std::map<int, int> m; 201 m.emplace(1,2); 202 m.emplace_hint(m.begin(), 0, 3); 203 } 204 { 205 std::set<int> s; 206 s.emplace(1); 207 s.emplace_hint(s.begin(), 0); 208 } 209 { 210 std::multimap<int, int> m; 211 m.emplace(1,2); 212 m.emplace_hint(m.begin(), 0, 3); 213 } 214 { 215 std::multiset<int> s; 216 s.emplace(1); 217 s.emplace_hint(s.begin(), 0); 218 } 219 { 220 std::vector<int> v; 221 v.emplace(v.begin(), 0); 222 v.emplace_back(1); 223 } 224 ]])],[ 225 AC_MSG_RESULT(yes) 226 have_cxx11_container_emplace=yes 227 ],[ 228 AC_MSG_RESULT(no) 229 ]) 230 231 dnl Reset the flags 232 CXXFLAGS="$old_CXXFLAGS" 233 AC_LANG_POP([C++]) 234 ]) 235 236dnl Test C++11 std::tuple and several related helper functions. 237AC_DEFUN([LIBMESH_TEST_CXX11_BEGIN_END], 238 [ 239 have_cxx11_begin_end=no 240 241 AC_MSG_CHECKING(for C++11 std::begin/end support for arrays) 242 AC_LANG_PUSH([C++]) 243 244 dnl For this and all of the C++ standards tests: Save the original 245 dnl CXXFLAGS (if any) before appending the $switch determined by 246 dnl AX_CXX_COMPILE_STDCXX_11, and any compiler flags specified by 247 dnl the user in the libmesh_CXXFLAGS environment variable, letting 248 dnl that override everything else. 249 old_CXXFLAGS="$CXXFLAGS" 250 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 251 252 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 253 @%:@include <iterator> 254 @%:@include <algorithm> 255 ]], [[ 256 int array[5] = {3, 1, 5, 2, 4}; 257 std::sort(std::begin(array), std::end(array)); 258 ]])],[ 259 AC_MSG_RESULT(yes) 260 have_cxx11_begin_end=yes 261 ],[ 262 AC_MSG_RESULT(no) 263 ]) 264 265 dnl Reset the flags 266 CXXFLAGS="$old_CXXFLAGS" 267 AC_LANG_POP([C++]) 268 ]) 269 270dnl Test C++11 std::tuple and several related helper functions. 271AC_DEFUN([LIBMESH_TEST_CXX11_TUPLE], 272 [ 273 have_cxx11_tuple=no 274 275 AC_MSG_CHECKING(for C++11 std::tuple support) 276 AC_LANG_PUSH([C++]) 277 278 dnl For this and all of the C++ standards tests: Save the original 279 dnl CXXFLAGS (if any) before appending the $switch determined by 280 dnl AX_CXX_COMPILE_STDCXX_11, and any compiler flags specified by 281 dnl the user in the libmesh_CXXFLAGS environment variable, letting 282 dnl that override everything else. 283 old_CXXFLAGS="$CXXFLAGS" 284 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 285 286 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 287 @%:@include <tuple> 288 @%:@include <map> 289 @%:@include <string> 290 ]], [[ 291 // Test std::make_tuple 292 std::map<int, std::tuple<double, char, std::string>> students; 293 students[0] = std::make_tuple(3.8, 'A', "Lisa Simpson"); 294 students[1] = std::make_tuple(2.9, 'C', "Milhouse Van Houten"); 295 296 // Test templated std::get() method. 297 std::get<0>(students[0]); 298 std::get<1>(students[0]); 299 std::get<2>(students[0]); 300 301 // Test std::tie and std::ignore which are declared in the <tuple> header. 302 double gpa1; 303 std::string name1; 304 std::tie(gpa1, std::ignore, name1) = students[1]; 305 306 // Test std::tuple_cat(), which combines together one or more 307 // objects, not necessarily tuples, into a single tuple. 308 auto t = std::tuple_cat(students[0], students[1], std::make_pair("foo", 42)); 309 ]])],[ 310 AC_MSG_RESULT(yes) 311 AC_DEFINE(HAVE_CXX11_TUPLE, 1, [Flag indicating whether compiler supports std::move]) 312 have_cxx11_tuple=yes 313 ],[ 314 AC_MSG_RESULT(no) 315 ]) 316 317 dnl Reset the flags 318 CXXFLAGS="$old_CXXFLAGS" 319 AC_LANG_POP([C++]) 320 321 AM_CONDITIONAL(HAVE_CXX11_TUPLE, test x$have_cxx11_tuple == xyes) 322 ]) 323 324dnl Test C++11 fixed type enumerations. 325AC_DEFUN([LIBMESH_TEST_CXX11_FIXED_TYPE_ENUM], 326 [ 327 have_cxx11_fixed_type_enum=no 328 329 AC_MSG_CHECKING(for C++11 fixed type enumeration support) 330 AC_LANG_PUSH([C++]) 331 332 dnl For this and all of the C++ standards tests: Save the original 333 dnl CXXFLAGS (if any) before appending the $switch determined by 334 dnl AX_CXX_COMPILE_STDCXX_11, and any compiler flags specified by 335 dnl the user in the libmesh_CXXFLAGS environment variable, letting 336 dnl that override everything else. 337 old_CXXFLAGS="$CXXFLAGS" 338 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 339 340 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 341 enum Fruit : int {APPLE=0, ORANGE=1}; 342 ]], [[ 343 Fruit f = APPLE; 344 ]])],[ 345 AC_MSG_RESULT(yes) 346 AC_DEFINE(HAVE_CXX11_FIXED_TYPE_ENUM, 1, [Flag indicating whether compiler supports fixed type enumerations]) 347 have_cxx11_fixed_type_enum=yes 348 ],[ 349 AC_MSG_RESULT(no) 350 ]) 351 352 dnl Reset the flags 353 CXXFLAGS="$old_CXXFLAGS" 354 AC_LANG_POP([C++]) 355 356 AM_CONDITIONAL(HAVE_CXX11_FIXED_TYPE_ENUM, test x$have_cxx11_fixed_type_enum == xyes) 357 ]) 358 359dnl Test C++11 fixed type enumeration forward declarations. 360AC_DEFUN([LIBMESH_TEST_CXX11_FIXED_TYPE_ENUM_FWD], 361 [ 362 have_cxx11_fixed_type_enum_fwd=no 363 364 AC_MSG_CHECKING(for C++11 fixed type enumeration forward declaration support) 365 AC_LANG_PUSH([C++]) 366 367 old_CXXFLAGS="$CXXFLAGS" 368 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 369 370 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 371 @%:@include <iostream> 372 enum Foo : int; 373 void func(Foo f) { std::cout << f << std::endl; } 374 enum Foo : int { FOO0 = 0, FOO1 = 1, FOO2 = 2 }; 375 ]], [[ 376 func(FOO0); 377 func(FOO1); 378 func(FOO2); 379 ]])],[ 380 AC_MSG_RESULT(yes) 381 AC_DEFINE(HAVE_CXX11_FIXED_TYPE_ENUM_FWD, 1, [Flag indicating whether compiler supports fixed type enumerations]) 382 have_cxx11_fixed_type_enum_fwd=yes 383 ],[ 384 AC_MSG_RESULT(no) 385 ]) 386 387 dnl Reset the flags 388 CXXFLAGS="$old_CXXFLAGS" 389 AC_LANG_POP([C++]) 390 391 AM_CONDITIONAL(HAVE_CXX11_FIXED_TYPE_ENUM_FWD, test x$have_cxx11_fixed_type_enum_fwd == xyes) 392 ]) 393 394dnl Properly implemented move constructors require rvalue references, 395dnl std::move, and noexcept, so this tests for all of those features. 396AC_DEFUN([LIBMESH_TEST_CXX11_MOVE_CONSTRUCTORS], 397 [ 398 have_cxx11_move_constructors=no 399 400 AC_MSG_CHECKING(for C++11 move constructor support) 401 AC_LANG_PUSH([C++]) 402 403 old_CXXFLAGS="$CXXFLAGS" 404 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 405 406 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 407 @%:@include <utility> 408 class move_constructable_base 409 { 410 public: 411 move_constructable_base() {} 412 move_constructable_base(move_constructable_base && other) noexcept {} 413 }; 414 class move_constructable : public move_constructable_base 415 { 416 public: 417 move_constructable() {} 418 move_constructable(move_constructable && other) noexcept : move_constructable_base(std::move(other)) {} 419 }; 420 ]], [[ 421 move_constructable m1; 422 move_constructable m2(std::move(m1)); 423 ]])],[ 424 AC_MSG_RESULT(yes) 425 AC_DEFINE(HAVE_CXX11_MOVE_CONSTRUCTORS, 1, [Flag indicating whether compiler supports move construction]) 426 have_cxx11_move_constructors=yes 427 ],[ 428 AC_MSG_RESULT(no) 429 ]) 430 431 # Reset the flags 432 CXXFLAGS="$old_CXXFLAGS" 433 AC_LANG_POP([C++]) 434 435 AM_CONDITIONAL(HAVE_CXX11_MOVE_CONSTRUCTORS, test x$have_cxx11_move_constructors == xyes) 436 ]) 437 438 439AC_DEFUN([LIBMESH_TEST_CXX11_RANGEFOR], 440 [ 441 have_cxx11_rangefor=no 442 443 AC_MSG_CHECKING(for C++11 range-based for loop support) 444 AC_LANG_PUSH([C++]) 445 446 old_CXXFLAGS="$CXXFLAGS" 447 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 448 449 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 450 @%:@include <iostream> 451 @%:@include <vector> 452 void print(const std::vector<int> & v) 453 { 454 for (const int & x : v) 455 std::cout << x << ' '; 456 std::cout << std::endl; 457 } 458 ]], [[ 459 std::vector<int> v(3); 460 print(v); 461 ]])],[ 462 AC_MSG_RESULT(yes) 463 AC_DEFINE(HAVE_CXX11_RANGEFOR, 1, [Flag indicating whether compiler supports range-based for loops]) 464 have_cxx11_rangefor=yes 465 ],[ 466 AC_MSG_RESULT(no) 467 ]) 468 469 # Reset the flags 470 CXXFLAGS="$old_CXXFLAGS" 471 AC_LANG_POP([C++]) 472 473 AM_CONDITIONAL(HAVE_CXX11_RANGEFOR, test x$have_cxx11_rangefor == xyes) 474 ]) 475 476 477AC_DEFUN([LIBMESH_TEST_CXX11_DECLTYPE], 478 [ 479 have_cxx11_decltype=no 480 481 AC_MSG_CHECKING(for C++11 decltype support) 482 AC_LANG_PUSH([C++]) 483 484 old_CXXFLAGS="$CXXFLAGS" 485 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 486 487 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 488 @%:@include <vector> 489 ]], [[ 490 int a; 491 decltype(a) b; 492 std::vector<int> vec(10); 493 for (auto i = decltype(vec.size())(0); i < vec.size(); ++i) 494 vec[i] += i; 495 ]])],[ 496 AC_MSG_RESULT(yes) 497 AC_DEFINE(HAVE_CXX11_DECLTYPE, 1, [Flag indicating whether compiler supports decltype]) 498 have_cxx11_decltype=yes 499 ],[ 500 AC_MSG_RESULT(no) 501 ]) 502 503 # Reset the flags 504 CXXFLAGS="$old_CXXFLAGS" 505 AC_LANG_POP([C++]) 506 507 AM_CONDITIONAL(HAVE_CXX11_DECLTYPE, test x$have_cxx11_decltype == xyes) 508 ]) 509 510 511AC_DEFUN([LIBMESH_TEST_CXX11_RVALUE_REFERENCES], 512 [ 513 have_cxx11_rvalue_references=no 514 515 AC_MSG_CHECKING(for C++11 rvalue references support) 516 AC_LANG_PUSH([C++]) 517 518 old_CXXFLAGS="$CXXFLAGS" 519 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 520 521 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 522 int foo(int && x) { return x; } 523 int bar() { return 4; } 524 ]], [[ 525 // Call function that takes an rvalue reference. 526 foo (bar()); 527 ]])],[ 528 AC_MSG_RESULT(yes) 529 AC_DEFINE(HAVE_CXX11_RVALUE_REFERENCES, 1, [Flag indicating whether compiler supports rvalue references]) 530 have_cxx11_rvalue_references=yes 531 ],[ 532 AC_MSG_RESULT(no) 533 ]) 534 535 # Reset the flags 536 CXXFLAGS="$old_CXXFLAGS" 537 AC_LANG_POP([C++]) 538 539 AM_CONDITIONAL(HAVE_CXX11_RVALUE_REFERENCES, test x$have_cxx11_rvalue_references == xyes) 540 ]) 541 542 543AC_DEFUN([LIBMESH_TEST_CXX11_AUTO], 544 [ 545 have_cxx11_auto=no 546 547 AC_MSG_CHECKING(for C++11 auto keyword support) 548 AC_LANG_PUSH([C++]) 549 550 old_CXXFLAGS="$CXXFLAGS" 551 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 552 553 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 554 ]], [[ 555 int x = 5; 556 auto y = x; 557 ]])],[ 558 AC_MSG_RESULT(yes) 559 AC_DEFINE(HAVE_CXX11_AUTO, 1, [Flag indicating whether compiler supports the auto keyword]) 560 have_cxx11_auto=yes 561 ],[ 562 AC_MSG_RESULT(no) 563 ]) 564 565 # Reset the flags 566 CXXFLAGS="$old_CXXFLAGS" 567 AC_LANG_POP([C++]) 568 569 AM_CONDITIONAL(HAVE_CXX11_AUTO, test x$have_cxx11_auto == xyes) 570 ]) 571 572 573AC_DEFUN([LIBMESH_TEST_CXX11_LAMBDA], 574 [ 575 have_cxx11_lambda=no 576 577 AC_MSG_CHECKING(for C++11 lambda support) 578 AC_LANG_PUSH([C++]) 579 580 old_CXXFLAGS="$CXXFLAGS" 581 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 582 583 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 584 // typedef for a function pointer that takes int and returns bool. 585 typedef bool (*FunctionPointer) (int); 586 587 // A function that takes a pointer to a function that takes an int, 588 // calls it with the number 4, and returns the result. 589 bool f(FunctionPointer g) { return g(4); } 590 ]], [[ 591 // Call f, passing it a lambda constructed on the fly instead 592 // of a standard function pointer. The result should be true. 593 f ( [](int x) { return x > 3; } ); 594 ]])],[ 595 AC_MSG_RESULT(yes) 596 AC_DEFINE(HAVE_CXX11_LAMBDA, 1, [Flag indicating whether compiler supports lambdas]) 597 have_cxx11_lambda=yes 598 ],[ 599 AC_MSG_RESULT(no) 600 ]) 601 602 # Reset the flags 603 CXXFLAGS="$old_CXXFLAGS" 604 AC_LANG_POP([C++]) 605 606 AM_CONDITIONAL(HAVE_CXX11_LAMBDA, test x$have_cxx11_lambda == xyes) 607 ]) 608 609 610AC_DEFUN([LIBMESH_TEST_CXX11_CONSTEXPR], 611 [ 612 have_cxx11_constexpr=no 613 614 AC_MSG_CHECKING(for C++11 constexpr support) 615 AC_LANG_PUSH([C++]) 616 617 old_CXXFLAGS="$CXXFLAGS" 618 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 619 620 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 621 constexpr int multiply (int x, int y) { return x * y; } 622 ]], [[ 623 // The compiler should compute "val" at compile time. 624 const int val = multiply(10, 10); 625 ]])],[ 626 AC_MSG_RESULT(yes) 627 AC_DEFINE(HAVE_CXX11_CONSTEXPR, 1, [Flag indicating whether compiler supports constexpr]) 628 have_cxx11_constexpr=yes 629 ],[ 630 AC_MSG_RESULT(no) 631 ]) 632 633 # Reset the flags 634 CXXFLAGS="$old_CXXFLAGS" 635 AC_LANG_POP([C++]) 636 637 AM_CONDITIONAL(HAVE_CXX11_CONSTEXPR, test x$have_cxx11_constexpr == xyes) 638 ]) 639 640 641AC_DEFUN([LIBMESH_TEST_CXX11_ALIAS_DECLARATIONS], 642 [ 643 have_cxx11_alias_declarations=no 644 645 AC_MSG_CHECKING(for C++11 alias declarations support) 646 AC_LANG_PUSH([C++]) 647 648 old_CXXFLAGS="$CXXFLAGS" 649 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 650 651 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 652 template <typename T> 653 struct check 654 { 655 T t; 656 }; 657 658 // An alias declaration is like a templated typedef 659 template <typename T> 660 using MyCheck = check<T>; 661 ]], [[ 662 MyCheck<int> mc; 663 ]])],[ 664 AC_MSG_RESULT(yes) 665 AC_DEFINE(HAVE_CXX11_ALIAS_DECLARATIONS, 1, [Flag indicating whether compiler supports alias declarations]) 666 have_cxx11_alias_declarations=yes 667 ],[ 668 AC_MSG_RESULT(no) 669 ]) 670 671 # Reset the flags 672 CXXFLAGS="$old_CXXFLAGS" 673 AC_LANG_POP([C++]) 674 675 AM_CONDITIONAL(HAVE_CXX11_ALIAS_DECLARATIONS, test x$have_cxx11_alias_declarations == xyes) 676 ]) 677 678 679AC_DEFUN([LIBMESH_TEST_CXX11_SHARED_PTR], 680 [ 681 have_cxx11_shared_ptr=no 682 683 AC_MSG_CHECKING(for C++11 std::shared_ptr support) 684 AC_LANG_PUSH([C++]) 685 686 # Save any original value that CXXFLAGS had 687 old_CXXFLAGS="$CXXFLAGS" 688 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 689 690 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 691 @%:@include <memory> 692 ]], [[ 693 std::shared_ptr<int> p1; 694 std::shared_ptr<int> p2 (new int); 695 std::shared_ptr<int> p3 (p2); 696 p3.reset(new int); 697 p3 = std::make_shared<int>(5); 698 ]])],[ 699 have_cxx11_shared_ptr=yes 700 AC_MSG_RESULT(yes) 701 ],[ 702 have_cxx11_shared_ptr=no 703 AC_MSG_RESULT(no) 704 ]) 705 706 dnl Only set the header file variable if our flag was set to 'yes'. 707 AS_IF([test "x$have_cxx11_shared_ptr" = "xyes"], 708 [AC_DEFINE(HAVE_CXX11_SHARED_PTR, 1, [Flag indicating whether compiler supports std::shared_ptr])]) 709 710 # Reset the flags 711 CXXFLAGS="$old_CXXFLAGS" 712 AC_LANG_POP([C++]) 713 714 AM_CONDITIONAL(HAVE_CXX11_SHARED_PTR, test x$have_cxx11_shared_ptr == xyes) 715 ]) 716 717 718AC_DEFUN([LIBMESH_TEST_CXX11_UNIQUE_PTR], 719 [ 720 have_cxx11_unique_ptr=no 721 722 AC_MSG_CHECKING(for C++11 std::unique_ptr support) 723 AC_LANG_PUSH([C++]) 724 725 old_CXXFLAGS="$CXXFLAGS" 726 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 727 728 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 729 @%:@include <iostream> 730 @%:@include <memory> 731 struct Foo 732 { 733 Foo() { std::cout << "Foo::Foo\n"; } 734 ~Foo() { std::cout << "Foo::~Foo\n"; } 735 }; 736 ]], [[ 737 { 738 // up now owns a Foo 739 std::unique_ptr<Foo> up(new Foo); 740 } // Foo deleted when up goes out of scope 741 ]])],[ 742 AC_MSG_RESULT(yes) 743 AC_DEFINE(HAVE_CXX11_UNIQUE_PTR, 1, [Flag indicating whether compiler supports std::unique_ptr]) 744 have_cxx11_unique_ptr=yes 745 ],[ 746 AC_MSG_RESULT(no) 747 ]) 748 749 # Reset the flags 750 CXXFLAGS="$old_CXXFLAGS" 751 AC_LANG_POP([C++]) 752 753 AM_CONDITIONAL(HAVE_CXX11_UNIQUE_PTR, test x$have_cxx11_unique_ptr == xyes) 754 ]) 755 756 757AC_DEFUN([LIBMESH_TEST_CXX14_MAKE_UNIQUE], 758 [ 759 have_cxx14_make_unique=no 760 761 # std::make_unique is actually part of the C++14 standard, but some 762 # compilers might (?) support it via the -std=c++11 flag, or eventually 763 # with no flag at all. 764 AC_MSG_CHECKING(for C++14 std::make_unique support) 765 AC_LANG_PUSH([C++]) 766 767 old_CXXFLAGS="$CXXFLAGS" 768 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 769 770 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 771 @%:@include <memory> 772 ]], [[ 773 { 774 // Normally, you would use "auto" on the LHS here to avoid 775 // repeating the type name, but we are not testing auto here. 776 std::unique_ptr<int> up = std::make_unique<int>(42); 777 } // Foo deleted when up goes out of scope 778 ]])],[ 779 AC_MSG_RESULT(yes) 780 AC_DEFINE(HAVE_CXX14_MAKE_UNIQUE, 1, [Flag indicating whether compiler supports std::make_unique]) 781 have_cxx14_make_unique=yes 782 ],[ 783 AC_MSG_RESULT(no) 784 ]) 785 786 # Reset the flags 787 CXXFLAGS="$old_CXXFLAGS" 788 AC_LANG_POP([C++]) 789 790 AM_CONDITIONAL(HAVE_CXX14_MAKE_UNIQUE, test x$have_cxx14_make_unique == xyes) 791 ]) 792 793 794AC_DEFUN([LIBMESH_TEST_CXX11_MAKE_UNIQUE_WORKAROUND], 795 [ 796 have_cxx11_make_unique_workaround=no 797 798 # This is a simple workaround for no std::make_unique in C++11: 799 # http://stackoverflow.com/questions/7038357/make-unique-and-perfect-forwarding 800 # Requires working rvalue references, std::forward, variadic 801 # templates, and std::unique_ptr from C++11. 802 AC_MSG_CHECKING(for C++11 std::make_unique workaround support) 803 AC_LANG_PUSH([C++]) 804 805 old_CXXFLAGS="$CXXFLAGS" 806 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 807 808 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 809 @%:@include <memory> 810 namespace local 811 { 812 template<typename T, typename... Args> 813 std::unique_ptr<T> make_unique(Args&&... args) 814 { 815 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 816 } 817 } 818 ]], [[ 819 { 820 // Normally, you would use "auto" on the LHS here to avoid 821 // repeating the type name, but we are not testing auto here. 822 std::unique_ptr<int> up = local::make_unique<int>(42); 823 } // Foo deleted when up goes out of scope 824 ]])],[ 825 AC_MSG_RESULT(yes) 826 AC_DEFINE(HAVE_CXX11_MAKE_UNIQUE_WORKAROUND, 1, [Flag indicating whether compiler supports C++11 std::make_unique workaround]) 827 have_cxx11_make_unique_workaround=yes 828 ],[ 829 AC_MSG_RESULT(no) 830 ]) 831 832 # Reset the flags 833 CXXFLAGS="$old_CXXFLAGS" 834 AC_LANG_POP([C++]) 835 836 AM_CONDITIONAL(HAVE_CXX11_MAKE_UNIQUE_WORKAROUND, test x$have_cxx11_make_unique_workaround == xyes) 837 ]) 838 839 840 841 842AC_DEFUN([LIBMESH_TEST_CXX11_REGEX], 843 [ 844 have_cxx11_regex=no 845 846 AC_MSG_CHECKING(for C++11 std::regex support) 847 AC_LANG_PUSH([C++]) 848 849 old_CXXFLAGS="$CXXFLAGS" 850 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 851 852 dnl We actually have to try and *run* the test program, since 853 dnl GCC up to 4.8 will compile this but then is not able to run it. 854 dnl GCC 4.9.1 and Clang 3.5 are actually able to run this test code. 855 dnl 856 dnl Note the quadruple backslash below -- this is needed so it 857 dnl expands to 2 backslashes in the test program generated by 858 dnl Autoconf... 859 AC_RUN_IFELSE([AC_LANG_PROGRAM([[ 860 @%:@include <regex> 861 ]], [[ 862 std::regex integer_regex("(\\\\+|-)?[[:digit:]]+"); 863 std::regex_match("abc", integer_regex); 864 std::regex_match("123", integer_regex); 865 ]])],[ 866 AC_MSG_RESULT(yes) 867 AC_DEFINE(HAVE_CXX11_REGEX, 1, [Flag indicating whether compiler supports std::regex]) 868 have_cxx11_regex=yes 869 ],[ 870 AC_MSG_RESULT(no) 871 ],[ 872 dnl The test program is not run when cross-compiling, so you are supposed to 873 dnl provide a "pessimistic" action here. We'll just assume the compiler does 874 dnl not support C++11 regexes in this case. 875 AC_MSG_RESULT(no) 876 ]) 877 878 # Reset the flags 879 CXXFLAGS="$old_CXXFLAGS" 880 AC_LANG_POP([C++]) 881 882 AM_CONDITIONAL(HAVE_CXX11_REGEX, test x$have_cxx11_regex == xyes) 883 ]) 884 885 886AC_DEFUN([LIBMESH_TEST_CXX11_OVERRIDE], 887 [ 888 have_cxx11_override=no 889 890 AC_MSG_CHECKING(for C++11 override keyword support) 891 AC_LANG_PUSH([C++]) 892 893 old_CXXFLAGS="$CXXFLAGS" 894 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 895 896 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 897 ]], [[ 898 struct Base { 899 virtual void f() {} 900 }; 901 struct Child : public Base { 902 virtual void f() override {} 903 }; 904 ]])],[ 905 AC_MSG_RESULT(yes) 906 AC_DEFINE(HAVE_CXX11_OVERRIDE, 1, [Flag indicating whether compiler supports the override keyword]) 907 have_cxx11_override=yes 908 ],[ 909 AC_MSG_RESULT(no) 910 ]) 911 912 # Reset the flags 913 CXXFLAGS="$old_CXXFLAGS" 914 AC_LANG_POP([C++]) 915 916 AM_CONDITIONAL(HAVE_CXX11_OVERRIDE, test x$have_cxx11_override == xyes) 917 ]) 918 919 920 921AC_DEFUN([LIBMESH_TEST_CXX11_INITIALIZER_LIST], 922 [ 923 have_cxx11_initializer_list=no 924 925 AC_MSG_CHECKING(for C++11 initializer list support) 926 AC_LANG_PUSH([C++]) 927 928 old_CXXFLAGS="$CXXFLAGS" 929 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 930 931 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 932 @%:@include <vector> 933 @%:@include <string> 934 ]], [[ 935 std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" }; 936 ]])],[ 937 AC_MSG_RESULT(yes) 938 AC_DEFINE(HAVE_CXX11_INITIALIZER_LIST, 1, [Flag indicating whether compiler supports initializer lists]) 939 have_cxx11_initializer_list=yes 940 ],[ 941 AC_MSG_RESULT(no) 942 ]) 943 944 # Reset the flags 945 CXXFLAGS="$old_CXXFLAGS" 946 AC_LANG_POP([C++]) 947 948 AM_CONDITIONAL(HAVE_CXX11_INITIALIZER_LIST, test x$have_cxx11_initializer_list == xyes) 949 ]) 950 951 952AC_DEFUN([LIBMESH_TEST_CXX11_VARIADIC_TEMPLATES], 953 [ 954 have_cxx11_variadic_templates=no 955 956 AC_MSG_CHECKING(for C++11 variadic template support) 957 AC_LANG_PUSH([C++]) 958 959 old_CXXFLAGS="$CXXFLAGS" 960 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 961 962 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 963 // Base case 964 template <typename T> 965 T sum(T t) { return t; } 966 967 // Compute sum of arbitrary number of passed parameters. 968 template <typename T, typename ...P> 969 T sum(T t, P ...p) 970 { 971 t += sum(p...); 972 return t; 973 } 974 ]], [[ 975 sum(1, 2, 3, 4, 5); 976 ]])],[ 977 AC_MSG_RESULT(yes) 978 AC_DEFINE(HAVE_CXX11_VARIADIC_TEMPLATES, 1, [Flag indicating whether compiler supports variadic templates]) 979 have_cxx11_variadic_templates=yes 980 ],[ 981 AC_MSG_RESULT(no) 982 ]) 983 984 # Reset the flags 985 CXXFLAGS="$old_CXXFLAGS" 986 AC_LANG_POP([C++]) 987 988 AM_CONDITIONAL(HAVE_CXX11_VARIADIC_TEMPLATES, test x$have_cxx11_variadic_templates == xyes) 989 ]) 990 991 992AC_DEFUN([LIBMESH_TEST_CXX11_THREAD], 993 [ 994 have_cxx11_thread=no 995 996 AC_MSG_CHECKING(for C++11 <thread> support) 997 AC_LANG_PUSH([C++]) 998 999 old_CXXFLAGS="$CXXFLAGS" 1000 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1001 1002 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1003 @%:@include <thread> 1004 @%:@include <atomic> 1005 @%:@include <mutex> 1006 void my_thread_func() {} 1007 ]], [[ 1008 thread_local int i; 1009 std::thread t(my_thread_func); 1010 t.join(); 1011 1012 std::atomic<bool> ab1, ab2; 1013 ab1.store(true, std::memory_order_relaxed); 1014 ab2.store(false, std::memory_order_relaxed); 1015 ab1.exchange(ab2); 1016 1017 std::mutex m; 1018 std::lock_guard<std::mutex> lock(m); 1019 1020 std::atomic_thread_fence(std::memory_order_acquire); 1021 std::atomic_thread_fence(std::memory_order_release); 1022 1023 // We use this function in one of our unit tests now. 1024 unsigned int n_threads = std::thread::hardware_concurrency(); 1025 ]])],[ 1026 AC_MSG_RESULT(yes) 1027 AC_DEFINE(HAVE_CXX11_THREAD, 1, [Flag indicating whether compiler supports std::thread]) 1028 have_cxx11_thread=yes 1029 ],[ 1030 AC_MSG_RESULT(no) 1031 ]) 1032 1033 # Reset the flags 1034 CXXFLAGS="$old_CXXFLAGS" 1035 AC_LANG_POP([C++]) 1036 1037 AM_CONDITIONAL(HAVE_CXX11_THREAD, test x$have_cxx11_thread == xyes) 1038 ]) 1039 1040 1041AC_DEFUN([LIBMESH_TEST_CXX11_CONDITION_VARIABLE], 1042 [ 1043 have_cxx11_condition_variable=no 1044 1045 AC_MSG_CHECKING(for C++11 <condition_variable> support) 1046 AC_LANG_PUSH([C++]) 1047 1048 old_CXXFLAGS="$CXXFLAGS" 1049 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1050 1051 # Test code is from the accepted answer on: 1052 # http://stackoverflow.com/questions/16350473/why-do-i-need-stdcondition-variable 1053 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1054 @%:@include <iostream> 1055 @%:@include <condition_variable> 1056 @%:@include <mutex> 1057 @%:@include <thread> 1058 @%:@include <chrono> 1059 1060 bool is_ready = false; 1061 std::mutex m; 1062 std::condition_variable cv; 1063 1064 void 1065 test() 1066 { 1067 std::this_thread::sleep_for(std::chrono::seconds(30)); 1068 std::unique_lock<std::mutex> ulock(m); 1069 is_ready = true; 1070 cv.notify_one(); 1071 } 1072 ]], [[ 1073 std::thread t(test); 1074 std::unique_lock<std::mutex> ulock(m); 1075 while (!is_ready) 1076 { 1077 cv.wait(ulock); 1078 if (!is_ready) 1079 std::cout << "Spurious wake up!\n"; 1080 } 1081 t.join(); 1082 ]])],[ 1083 AC_MSG_RESULT(yes) 1084 AC_DEFINE(HAVE_CXX11_CONDITION_VARIABLE, 1, [Flag indicating whether compiler supports std::condition_variable]) 1085 have_cxx11_condition_variable=yes 1086 ],[ 1087 AC_MSG_RESULT(no) 1088 ]) 1089 1090 # Reset the flags 1091 CXXFLAGS="$old_CXXFLAGS" 1092 AC_LANG_POP([C++]) 1093 1094 AM_CONDITIONAL(HAVE_CXX11_CONDITION_VARIABLE, test x$have_cxx11_condition_variable == xyes) 1095 ]) 1096 1097 1098 1099AC_DEFUN([LIBMESH_TEST_CXX11_TYPE_TRAITS], 1100 [ 1101 # This is designed to be an exhaustive test of the capabilities of 1102 # the <type_traits> header, as defined by the C++11 standard. We 1103 # don't use all of these in libmesh, but we want application code 1104 # to be able to rely on the value of LIBMESH_HAVE_CXX11_TYPE_TRAITS. 1105 # 1106 # Not all compilers fully implement the header. For example, GCC 1107 # 4.9.1 does not provide the is_trivially_copyable() function, but 1108 # it does provide support for other <type_traits> functions. 1109 # 1110 # See also: 1111 # http://en.cppreference.com/w/cpp/header/type_traits 1112 have_cxx11_type_traits=no 1113 1114 AC_MSG_CHECKING(for C++11 <type_traits> support) 1115 AC_LANG_PUSH([C++]) 1116 1117 old_CXXFLAGS="$CXXFLAGS" 1118 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1119 1120 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1121 @%:@include <iostream> 1122 @%:@include <type_traits> 1123 1124 // std::enable_if - the return type of the function is only defined if 1125 // T is an integral type. Therefore, it's a *compile* error if you 1126 // try to call it with a non-integral type. 1127 template <class T> 1128 typename std::enable_if<std::is_integral<T>::value, bool>::type 1129 is_odd (T i) 1130 { 1131 return static_cast<bool>(i%2); 1132 } 1133 1134 // std::underlying_type - names the underlying type of an enum 1135 enum e1 {}; 1136 1137 // typedef (named fn_ptr) for a function that takes nothing and returns char. 1138 typedef char (*fn_ptr)(); 1139 ]], [[ 1140 std::cout << std::is_void<char>::value 1141 // << std::is_null_pointer<char>::value // C++14 1142 << std::is_integral<char>::value 1143 << std::is_floating_point<char>::value 1144 << std::is_array<char>::value 1145 << std::is_enum<char>::value 1146 << std::is_union<char>::value 1147 << std::is_class<char>::value 1148 << std::is_function<char>::value 1149 << std::is_pointer<char>::value 1150 << std::is_lvalue_reference<char>::value 1151 << std::is_rvalue_reference<char>::value 1152 << std::is_member_object_pointer<char>::value 1153 << std::is_fundamental<char>::value 1154 << std::is_arithmetic<char>::value 1155 << std::is_scalar<char>::value 1156 << std::is_object<char>::value 1157 << std::is_compound<char>::value 1158 << std::is_reference<char>::value 1159 << std::is_member_pointer<char>::value 1160 << std::is_const<char>::value 1161 << std::is_volatile<char>::value 1162 << std::is_trivial<char>::value 1163 << std::is_trivially_copyable<char>::value // Not supported by GCC 4.6.3 with -std=c++0x 1164 << std::is_standard_layout<char>::value 1165 << std::is_pod<char>::value 1166 << std::is_literal_type<char>::value 1167 << std::is_empty<char>::value 1168 << std::is_polymorphic<char>::value 1169 << std::is_abstract<char>::value 1170 << std::is_signed<char>::value 1171 << std::is_unsigned<char>::value 1172 << std::is_constructible<char>::value 1173 << std::is_trivially_constructible<char>::value 1174 << std::is_nothrow_constructible<char>::value 1175 << std::is_default_constructible<char>::value 1176 << std::is_trivially_default_constructible<char>::value 1177 << std::is_nothrow_default_constructible<char>::value 1178 << std::is_copy_constructible<char>::value 1179 << std::is_trivially_copy_constructible<char>::value 1180 << std::is_nothrow_copy_constructible<char>::value 1181 << std::is_move_constructible<char>::value 1182 << std::is_trivially_move_constructible<char>::value 1183 << std::is_nothrow_move_constructible<char>::value 1184 << std::is_assignable<char, char>::value 1185 << std::is_trivially_assignable<char, char>::value 1186 << std::is_nothrow_assignable<char, char>::value 1187 << std::is_copy_assignable<char>::value 1188 << std::is_trivially_copy_assignable<char>::value 1189 << std::is_nothrow_copy_assignable<char>::value 1190 << std::is_move_assignable<char>::value 1191 << std::is_trivially_move_assignable<char>::value 1192 << std::is_nothrow_move_assignable<char>::value 1193 << std::is_destructible<char>::value 1194 << std::is_trivially_destructible<char>::value 1195 << std::is_nothrow_destructible<char>::value 1196 << std::has_virtual_destructor<char>::value 1197 << std::alignment_of<char>::value 1198 << std::rank<char>::value 1199 << std::extent<char>::value 1200 << std::is_same<char, char>::value 1201 << std::is_base_of<char, char>::value 1202 << std::is_convertible<char, char>::value 1203 << std::is_same<char, std::remove_cv<const char>::type>::value // std::remove_cv 1204 << std::is_same<char, std::remove_const<const char>::type>::value // std::remove_const 1205 << std::is_same<char, std::remove_volatile<volatile char>::type>::value // std::remove_volatile 1206 << std::is_same<const volatile char, std::add_cv<char>::type>::value // std::add_cv 1207 << std::is_same<const char, std::add_const<char>::type>::value // std::add_const 1208 << std::is_same<volatile char, std::add_volatile<char>::type>::value // std::add_volatile 1209 << std::is_same<char, std::remove_reference<char &>::type>::value // std::remove_reference 1210 << std::is_same<char &, std::add_lvalue_reference<char>::type>::value // std::add_lvalue_reference 1211 << std::is_same<char &&, std::add_rvalue_reference<char>::type>::value // std::add_rvalue_reference 1212 << std::is_same<char, std::remove_pointer<char *>::type>::value // std::remove_pointer 1213 << std::is_same<char *, std::add_pointer<char>::type>::value // std::add_pointer 1214 << std::is_same<char, std::make_signed<unsigned char>::type>::value // std::make_signed 1215 << std::is_same<unsigned char, std::make_unsigned<char>::type>::value // std::make_unsigned 1216 << std::is_same<char, std::remove_extent<char>::type>::value // std::remove_extent 1217 << std::is_same<char, std::remove_all_extents<char>::type>::value // std::remove_all_extents 1218 << std::is_same<char, std::decay<const char &>::type>::value // std::decay 1219 << is_odd(13) // std::enable_if 1220 << std::is_same<char, std::conditional<true, /*type if true*/char, /*type if false*/int>::type>::value // std::conditional 1221 << std::is_same<long, std::common_type<char, short, int, long>::type>::value // std::common_type 1222 << std::is_same<int, std::underlying_type<e1>::type>::value // std::underlying_type 1223 << std::is_same<char, std::result_of<fn_ptr()>::type>::value // std::result_of 1224 << std::false_type::value 1225 << std::true_type::value 1226 << std::endl; 1227 1228 // std::aligned_storage 1229 typedef std::aligned_storage</*store objects of length=*/1>::type aligned_t; 1230 1231 // std::aligned_union 1232 typedef std::aligned_union</*size of at least*/32, int, char, double>::type union_t; 1233 ]])],[ 1234 AC_MSG_RESULT(yes) 1235 AC_DEFINE(HAVE_CXX11_TYPE_TRAITS, 1, [Flag indicating whether compiler supports <type_traits>]) 1236 have_cxx11_type_traits=yes 1237 ],[ 1238 AC_MSG_RESULT(no) 1239 ]) 1240 1241 # Reset the flags 1242 CXXFLAGS="$old_CXXFLAGS" 1243 AC_LANG_POP([C++]) 1244 1245 AM_CONDITIONAL(HAVE_CXX11_TYPE_TRAITS, test x$have_cxx11_type_traits == xyes) 1246 ]) 1247 1248 1249AC_DEFUN([LIBMESH_TEST_CXX11_MATH_FUNCS], 1250 [ 1251 have_cxx11_inverse_hyperbolic_sine=no 1252 have_cxx11_inverse_hyperbolic_cosine=no 1253 have_cxx11_inverse_hyperbolic_tangent=no 1254 1255 have_cxx11_inverse_hyperbolic_sine_complex=no 1256 have_cxx11_inverse_hyperbolic_cosine_complex=no 1257 have_cxx11_inverse_hyperbolic_tangent_complex=no 1258 1259 AC_LANG_PUSH([C++]) 1260 1261 old_CXXFLAGS="$CXXFLAGS" 1262 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1263 1264 # Test for asinh 1265 AC_MSG_CHECKING(for C++11 std::asinh support in <cmath>) 1266 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1267 @%:@include <cmath> 1268 ]], [[ 1269 double x = std::asinh(1.); 1270 ]])],[ 1271 AC_MSG_RESULT(yes) 1272 AC_DEFINE(HAVE_CXX11_INVERSE_HYPERBOLIC_SINE, 1, [Flag indicating whether compiler supports std::asinh]) 1273 have_cxx11_inverse_hyperbolic_sine=yes 1274 ],[ 1275 AC_MSG_RESULT(no) 1276 ]) 1277 1278 # Test for acosh 1279 AC_MSG_CHECKING(for C++11 std::acosh support in <cmath>) 1280 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1281 @%:@include <cmath> 1282 ]], [[ 1283 double x = std::acosh(1.); 1284 ]])],[ 1285 AC_MSG_RESULT(yes) 1286 AC_DEFINE(HAVE_CXX11_INVERSE_HYPERBOLIC_COSINE, 1, [Flag indicating whether compiler supports std::acosh]) 1287 have_cxx11_inverse_hyperbolic_cosine=yes 1288 ],[ 1289 AC_MSG_RESULT(no) 1290 ]) 1291 1292 # Test for atanh 1293 AC_MSG_CHECKING(for C++11 std::atanh support in <cmath>) 1294 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1295 @%:@include <cmath> 1296 ]], [[ 1297 double x = std::atanh(0.); 1298 ]])],[ 1299 AC_MSG_RESULT(yes) 1300 AC_DEFINE(HAVE_CXX11_INVERSE_HYPERBOLIC_TANGENT, 1, [Flag indicating whether compiler supports std::atanh]) 1301 have_cxx11_inverse_hyperbolic_tangent=yes 1302 ],[ 1303 AC_MSG_RESULT(no) 1304 ]) 1305 1306 1307 # Test for asinh(complex) 1308 AC_MSG_CHECKING(for C++11 std::asinh(complex) support in <complex>) 1309 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1310 @%:@include <complex> 1311 ]], [[ 1312 std::complex<double> z(0, -2); 1313 std::complex<double> x = std::asinh(z); 1314 ]])],[ 1315 AC_MSG_RESULT(yes) 1316 AC_DEFINE(HAVE_CXX11_INVERSE_HYPERBOLIC_SINE_COMPLEX, 1, [Flag indicating whether compiler supports std::asinh(complex)]) 1317 have_cxx11_inverse_hyperbolic_sine_complex=yes 1318 ],[ 1319 AC_MSG_RESULT(no) 1320 ]) 1321 1322 # Test for acosh(complex) 1323 AC_MSG_CHECKING(for C++11 std::acosh(complex) support in <complex>) 1324 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1325 @%:@include <complex> 1326 ]], [[ 1327 std::complex<double> z(0.5, 0); 1328 std::complex<double> x = std::acosh(z); 1329 ]])],[ 1330 AC_MSG_RESULT(yes) 1331 AC_DEFINE(HAVE_CXX11_INVERSE_HYPERBOLIC_COSINE_COMPLEX, 1, [Flag indicating whether compiler supports std::acosh(complex)]) 1332 have_cxx11_inverse_hyperbolic_cosine_complex=yes 1333 ],[ 1334 AC_MSG_RESULT(no) 1335 ]) 1336 1337 # Test for atanh(complex) 1338 AC_MSG_CHECKING(for C++11 std::atanh(complex) support in <complex>) 1339 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1340 @%:@include <complex> 1341 ]], [[ 1342 std::complex<double> z(2, 0); 1343 std::complex<double> x = std::atanh(z); 1344 ]])],[ 1345 AC_MSG_RESULT(yes) 1346 AC_DEFINE(HAVE_CXX11_INVERSE_HYPERBOLIC_TANGENT_COMPLEX, 1, [Flag indicating whether compiler supports std::atanh(complex)]) 1347 have_cxx11_inverse_hyperbolic_tangent_complex=yes 1348 ],[ 1349 AC_MSG_RESULT(no) 1350 ]) 1351 1352 # Test for erf 1353 AC_MSG_CHECKING(for C++11 std::erf support in <cmath>) 1354 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1355 @%:@include <cmath> 1356 ]], [[ 1357 double val = std::erf(1.); 1358 ]])],[ 1359 AC_MSG_RESULT(yes) 1360 AC_DEFINE(HAVE_CXX11_ERF, 1, [Flag indicating whether compiler supports std::erf]) 1361 have_cxx11_erf=yes 1362 ],[ 1363 AC_MSG_RESULT(no) 1364 ]) 1365 1366 1367 # Reset the flags 1368 CXXFLAGS="$old_CXXFLAGS" 1369 AC_LANG_POP([C++]) 1370 1371 AM_CONDITIONAL(HAVE_CXX11_INVERSE_HYPERBOLIC_SINE, test x$have_cxx11_inverse_hyperbolic_sine == xyes) 1372 AM_CONDITIONAL(HAVE_CXX11_INVERSE_HYPERBOLIC_COSINE, test x$have_cxx11_inverse_hyperbolic_cosine == xyes) 1373 AM_CONDITIONAL(HAVE_CXX11_INVERSE_HYPERBOLIC_TANGENT, test x$have_cxx11_inverse_hyperbolic_tangent == xyes) 1374 1375 AM_CONDITIONAL(HAVE_CXX11_INVERSE_HYPERBOLIC_SINE_COMPLEX, test x$have_cxx11_inverse_hyperbolic_sine_complex == xyes) 1376 AM_CONDITIONAL(HAVE_CXX11_INVERSE_HYPERBOLIC_COSINE_COMPLEX, test x$have_cxx11_inverse_hyperbolic_cosine_complex == xyes) 1377 AM_CONDITIONAL(HAVE_CXX11_INVERSE_HYPERBOLIC_TANGENT_COMPLEX, test x$have_cxx11_inverse_hyperbolic_tangent_complex == xyes) 1378 1379 AM_CONDITIONAL(HAVE_CXX11_ERF, test x$have_cxx11_erf == xyes) 1380 ]) 1381 1382 1383AC_DEFUN([LIBMESH_TEST_CXX11_DELETED_FUNCTIONS], 1384 [ 1385 have_cxx11_deleted_functions=no 1386 1387 AC_MSG_CHECKING(for C++11 deleted functions support) 1388 AC_LANG_PUSH([C++]) 1389 1390 old_CXXFLAGS="$CXXFLAGS" 1391 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1392 1393 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1394 class Foo 1395 { 1396 Foo(const Foo &) = delete; 1397 }; 1398 ]], [[ 1399 ]])],[ 1400 AC_MSG_RESULT(yes) 1401 AC_DEFINE(HAVE_CXX11_DELETED_FUNCTIONS, 1, [Flag indicating whether compiler supports f() = delete;]) 1402 have_cxx11_deleted_functions=yes 1403 ],[ 1404 AC_MSG_RESULT(no) 1405 ]) 1406 1407 # Reset the flags 1408 CXXFLAGS="$old_CXXFLAGS" 1409 AC_LANG_POP([C++]) 1410 1411 AM_CONDITIONAL(HAVE_CXX11_DELETED_FUNCTIONS, test x$have_cxx11_deleted_functions == xyes) 1412 ]) 1413 1414 1415AC_DEFUN([LIBMESH_TEST_CXX11_DEFAULTED_FUNCTIONS], 1416 [ 1417 have_cxx11_defaulted_functions=no 1418 1419 AC_MSG_CHECKING(for C++11 defaulted functions support) 1420 AC_LANG_PUSH([C++]) 1421 1422 old_CXXFLAGS="$CXXFLAGS" 1423 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1424 1425 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1426 class Foo 1427 { 1428 Foo(const Foo &) = default; 1429 ~Foo(); 1430 }; 1431 Foo::~Foo() = default; 1432 ]], [[ 1433 ]])],[ 1434 AC_MSG_RESULT(yes) 1435 AC_DEFINE(HAVE_CXX11_DEFAULTED_FUNCTIONS, 1, [Flag indicating whether compiler supports defaulted functions]) 1436 have_cxx11_defaulted_functions=yes 1437 ],[ 1438 AC_MSG_RESULT(no) 1439 ]) 1440 1441 # Reset the flags 1442 CXXFLAGS="$old_CXXFLAGS" 1443 AC_LANG_POP([C++]) 1444 1445 AM_CONDITIONAL(HAVE_CXX11_DEFAULTED_FUNCTIONS, test x$have_cxx11_defaulted_functions == xyes) 1446 ]) 1447 1448 1449AC_DEFUN([LIBMESH_TEST_CXX11_FINAL], 1450 [ 1451 have_cxx11_final=no 1452 1453 AC_MSG_CHECKING(for C++11 'final' keyword support) 1454 AC_LANG_PUSH([C++]) 1455 1456 old_CXXFLAGS="$CXXFLAGS" 1457 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1458 1459 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1460 // Test that a function can be declared final. 1461 struct A 1462 { 1463 virtual void foo() final; 1464 }; 1465 1466 // Test that a struct can be declared final. 1467 struct B final : A 1468 { 1469 }; 1470 ]], [[ 1471 ]])],[ 1472 have_cxx11_final=yes 1473 ],[ 1474 have_cxx11_final=no 1475 ]) 1476 1477 # Confirm that you cannot declare a non-virtual function 'final'. 1478 AS_IF([test "x$have_cxx11_final" != "xno"], 1479 [ 1480 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1481 struct A 1482 { 1483 // Error: non-virtual function cannot be final 1484 void bar() final; 1485 }; 1486 ]], [[ 1487 ]])],[ 1488 # If this code compiles, 'final' is not working correctly. 1489 have_cxx11_final=no 1490 ],[ 1491 have_cxx11_final=yes 1492 ]) 1493 ]) 1494 1495 dnl Confirm that you cannot override a final function. 1496 AS_IF([test "x$have_cxx11_final" != "xno"], 1497 [ 1498 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1499 struct A 1500 { 1501 virtual void foo() final; 1502 }; 1503 struct B : A 1504 { 1505 // Error: foo cannot be overridden as it's final in A 1506 void foo(); 1507 }; 1508 ]], [[ 1509 ]])],[ 1510 # If this code compiles, 'final' is not working correctly. 1511 have_cxx11_final=no 1512 ],[ 1513 have_cxx11_final=yes 1514 ]) 1515 ]) 1516 1517 dnl Confirm that you cannot inherit from a 'final' class. 1518 AS_IF([test "x$have_cxx11_final" != "xno"], 1519 [ 1520 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1521 struct A 1522 { 1523 }; 1524 1525 // struct B is final 1526 struct B final : A 1527 { 1528 }; 1529 1530 // Error: B is final 1531 struct C : B 1532 { 1533 }; 1534 ]], [[ 1535 ]])],[ 1536 # If this code compiles, 'final' is not working correctly. 1537 have_cxx11_final=no 1538 ],[ 1539 have_cxx11_final=yes 1540 ]) 1541 ]) 1542 1543 # If the flag is still 'yes' after all the tests, set the #define. 1544 AS_IF([test "x$have_cxx11_final" = "xyes"], 1545 [ 1546 AC_MSG_RESULT(yes) 1547 AC_DEFINE(HAVE_CXX11_FINAL, 1, [Flag indicating whether compiler supports f() final;]) 1548 ], 1549 [AC_MSG_RESULT(no)]) 1550 1551 # Reset the flags 1552 CXXFLAGS="$old_CXXFLAGS" 1553 AC_LANG_POP([C++]) 1554 1555 AM_CONDITIONAL(HAVE_CXX11_FINAL, test x$have_cxx11_final == xyes) 1556 ]) 1557 1558 1559AC_DEFUN([LIBMESH_TEST_CXX11_NULLPTR], 1560 [ 1561 have_cxx11_nullptr=no 1562 1563 AC_MSG_CHECKING(for C++11 nullptr support) 1564 AC_LANG_PUSH([C++]) 1565 1566 old_CXXFLAGS="$CXXFLAGS" 1567 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1568 1569 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1570 @%:@include <cstddef> 1571 void f(int * pi) {} 1572 void f(double * pd) {} 1573 void f(std::nullptr_t nullp) {} 1574 ]], [[ 1575 // would be ambiguous without void f(nullptr_t) 1576 f(nullptr); 1577 ]])],[ 1578 AC_MSG_RESULT(yes) 1579 AC_DEFINE(HAVE_CXX11_NULLPTR, 1, [Flag indicating whether compiler supports nullptr]) 1580 have_cxx11_nullptr=yes 1581 ],[ 1582 AC_MSG_RESULT(no) 1583 ]) 1584 1585 # Reset the flags 1586 CXXFLAGS="$old_CXXFLAGS" 1587 AC_LANG_POP([C++]) 1588 1589 AM_CONDITIONAL(HAVE_CXX11_NULLPTR, test x$have_cxx11_nullptr == xyes) 1590 ]) 1591 1592 1593 1594AC_DEFUN([LIBMESH_TEST_CXX11_TO_STRING], 1595 [ 1596 have_cxx11_to_string=no 1597 1598 AC_MSG_CHECKING(for C++11 std::to_string() support) 1599 AC_LANG_PUSH([C++]) 1600 1601 old_CXXFLAGS="$CXXFLAGS" 1602 CXXFLAGS="$CXXFLAGS $switch $libmesh_CXXFLAGS" 1603 1604 AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ 1605 @%:@include <string> 1606 ]], [[ 1607 // tiny="0.000000". Note: std::to_string(double) is required to produce 1608 // a std::string with the same contents as std::sprintf(buf, "%f", value) 1609 // would produce, given a sufficiently large buf. This is *different* from 1610 // what you get from a std::stringstream using default formatting and 1611 // precision flags, i.e. 1612 // std::ostringstream oss; 1613 // oss << 1.e-40; 1614 // std::string tiny = oss.str(); 1615 // will produce the string "1e-40". 1616 std::string tiny = std::to_string(1.e-40); 1617 ]])],[ 1618 AC_MSG_RESULT(yes) 1619 AC_DEFINE(HAVE_CXX11_TO_STRING, 1, [Flag indicating whether compiler supports std::to_string()]) 1620 have_cxx11_to_string=yes 1621 ],[ 1622 AC_MSG_RESULT(no) 1623 ]) 1624 1625 # Reset the flags 1626 CXXFLAGS="$old_CXXFLAGS" 1627 AC_LANG_POP([C++]) 1628 1629 AM_CONDITIONAL(HAVE_CXX11_TO_STRING, test x$have_cxx11_to_string == xyes) 1630 ]) 1631