With this minimum reproducible example, the build is successful, even though I want it to fail with an include error that <filesystem> doesn’t exist. It does in C++17, but our requirements state we can’t use it.
I could come up with a more thorough example with a library and two projects to prove the PUBLIC properties work as expected, however, I think this will suffice for now.
The above method to set the standard is what I read as recommended in Craig Scott’s book, as well as his post on stack overflow, but it only imposes a minimum requirement, not a maximum cap on language features.
CMake doesn’t provide a way to limit the language standard. It only provides a way to say “this thing needs at least language standard XXX”. A target can have a few different contributors to its required language standard, and CMake chooses the lowest language standard that satisfies all those requirements. It does not give you a way to say “don’t set the language standard to anything higher than XXX”.
That part of the book is going to be updated in the next edition (I’m actually in the middle of updating that specific part right now). With C++20 modules now potentially in the picture, things get a whole lot more complicated. You used to (typically) be able to get away with mixing different language standards in the one build, but you can’t any more once C++20 modules are involved. You need to have the same language standard used throughout or you run into problems with BMIs (built module interfaces). Not directly relevant to your specific query, but you’ll find the recommended pattern of setting the three CMAKE_... variables for the language standard and extensions will be more involved going forward.
If you wanted to make it in CMake and not modify the existing source/headers, you could put that little snippet from Ben into a check_source_compiles and then fail the CMake configure if check is successful.
Autosar C++14 and FACE™ 3.0 standards both limit to C++14. If one wants to certify the code, C++17 isn’t allowed, so it would be good to prohibit in CI rather than wait till certification time to realize you accidentally injected a bunch of C++17 code.