C++11: Is it time?

This keeps coming up and is in my opinion the current “elephant in the room”; are we requiring C++11 now? I figured I’d open a topic here so the issue doesn’t get lost in GitHub issues…

Best I can tell, this limits us to the following compilers:

  • Intel15 for full compliance (or Intel13 for about 90% compliance).
  • GCC 4.8 for full compliance. GCC 4.4 gives us about 90%
  • Clang 3.3 for full compliance. Clang 2.9 is 90%
    • There is a caveat of them not having to provide support for two features on their site…

As a slight aside, there also seem to be issues discovered by @loriab and @jturney suggesting that GCC 5+ breaks boost so we can’t go too new. Did I get that correct?

The newness of the compilers is my main concern. Stampede just updated to Intel 15 relatively recently, and still hasn’t recompiled all of their modules with it. So full support of C++11 would break our compatibility with at least that supercomputer. I anticipate that most supercomputers are on a similar cycle, so this time, next year, there likely won’t be any issues with C++11 support.

@loriab how about a development tag for questions related to how Psi4 development should proceed?

I’m not positive that the boost problem is specific to gcc 5+. On my Macs with homebrew, I cannot build using gcc-4.9+ or gcc-5+ because of a vast number of boost link errors. However, if I use the Apple gcc version (LLVM version 6.1.0 (clang-602.0.53), but only use gfortran-4.9+ or gfortran-5+ for externals like pcmsolver, then all is well. So I think this issue with boost goes further back.

I’ve run into issues linking Psi4 with Boost using gcc 5.2 on my Mac box. I haven’t been able to compile the actual gcc 5.2 compilers on my Linux box yet. Haven’t tried other versions of gcc.

We already require C++11 compiler support for Psi4. I’ve found a few cases of C++11 foreach style for loops. CMakeLists.txt should be modified to require it. The instance we’ve run into most recently is C++11 headers support. For A simple cmake test can determine if std::to_string is available and, if not, include our version of it.

I say we continue to use C++11 in the code but be modest in our usage…if it’s something in that 10% missing don’t use it. And if it is specific to C++11 header feature we test for it and adapt appropriately. We should also include additional boxes on the testboard checking different versions of gcc and icpc.

With Intel13 we are missing the following from C++11:

  • Forward declared enums
  • Strongly typed enums
  • Generalized constant expressions

Skimming over GCC4.4 and Clang2.9 it looks like the list is similar. Nothing is particularly critical or used that often.

For std::to_string it needs to check if all of the C++11 overloads are available, not just general availability.

This thread now has a “future-direction” category.

The gcc 5.2 issue has been seen on Linux, too, by Sahan. He tried gcc and intel compilers (both with MKL), and one failed in libmints (boost xpressive related) and one at link-stage. Hence the current advice: https://github.com/psi4/psi4public/wiki/9_CXX#-what-gcc-fundamental-libraries-are-approved . Moreover, boost isn’t testing against 5.2 yet: http://www.boost.org/users/history/version_1_58_0.html .

@dgasmith we are missing a bit more than that, but I suspect you are probably only highlighting what most people will use, if that’s the case I think you need to add initializer lists to that list

Aside from the range-based for loops in fsapt (I presume that’s what @jturney was referring to), and the std::to_string function, which most recently brought up this issue, the only other C++11 features I know of in Psi4 are some non-static inline member variable initializations in optking, and variadic templates in libfrag. Complaints about the latter seem to have subsided so I’m guessing they are no longer issues (?).

Despite what the Intel website says, the range-based for loops in fsapt do not compile for me with Intel 13 (the non-static inline member variables require Intel 14 according to Intel’s website and obviously also do not compile). I had also tried using lambdas at one point, but ran into problems with Intel 13, despite them supposedly being supported there as well (admittedly my use was non-trivial and may not have constituted a fair trial). Lines around 115 of cmake/compilers/CheckCXX11Features.cmake suggest that Intel 13’s support of C++11 is known to be buggy by @robertodr .

Getting back to @jturney’s idea of only using those features of the C++11 standard that are not missing from most compilers, as best as I can tell, variadic templates are the only demonstrated feature that work (ignoring things like std::to_string, which are a header issues) with Intel 13. Quite frankly, aside from rvalue references, variadic templates are the only C++11 feature I personally care about (I’m still using boost smart pointers, boost threading, and I have my own strong-typed enums that I use). Lambdas are nice, but I don’t think it’s a huge deal to write a functor if I need a lambda. I haven’t really seen what I would call a nice usage of an initializer list for a non POD type (initializer lists for POD types have always existed); constructors serve the same purpose for a derived type. The range-based for loops are clean and I do like them, but honestly I’m so used to not having them, that I’ll probably never use them. I absolutely hate the idea of auto, and will never use it unless I have to (the type of a lambda is an example of having to use it), because the compiler knowing the type and you knowing the type are two very different things…

edit: switched foreach to range-based for loop

@ryanmrichard The C++11 detection is deactivated for Intel 13 not because the compile doesn’t support it, but because of clashes with the standard headers. This I have observed on our cluster in Tromsø and was reported to me by others. For lack of a better C++11 detection mechanism, I chose the easy path of falling back to C++98/C++03 altogether with those compiler versions. The C++11 detection is not written in stone, so please modify it if you find a way to test for conflicting standard headers installations.
As of CMake 3.1 one can require compile features
I think they are implemented in much the same way as the C++11 detection macros we have in place right now, but in a standardized fashion. I do not know if they check on conflicting standard headers installations, though.

I’ve found Scott Meyers’ Effective Modern C++ very useful in understanding how C++ codebases can be improved by the use of the new standard. I can warmly recommend it.