Your approach would - as @Tsyvarev has commented - be absolutely fine, just since you've asked for the "new" approach in CMake here is what your code would translate to: 
cmake_minimum_required(VERSION 3.8)
project(HelloWorld)
string(
    APPEND _opts
    "$<IF:$<CXX_COMPILER_ID:MSVC>,"
        "/W4;$<$<CONFIG:RELEASE>:/O2>,"
        "-Wall;-Wextra;-Werror;"
            "$<$<CONFIG:RELEASE>:-O3>"
            "$<$<CXX_COMPILER_ID:Clang>:-stdlib=libc++>"
    ">"
)
add_compile_options("${_opts}")
add_executable(HelloWorld "main.cpp")
target_compile_features(HelloWorld PUBLIC cxx_lambda_init_captures)
You take add_compile_options() and - as @Al.G. has commented - "use the dirty generator expressions". 
There are some downsides of generator expressions:
- The very helpful $<IF:...,...,...>expression is only available in CMake version >= 3.8
- You have to write it in a single line. To avoid it I used the string(APPEND ...), which you can also use to "optimize" yourset(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ...calls.
- It's difficult to read and understand. E.g. the semicolons are needed to make it a list of compile options (otherwise CMake will quote it).
So better use a more readable and backward compatible approach with add_compile_options():
if(MSVC)
    add_compile_options("/W4" "$<$<CONFIG:RELEASE>:/O2>")
else()
    add_compile_options("-Wall" "-Wextra" "-Werror" "$<$<CONFIG:RELEASE>:-O3>")
    if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        add_compile_options("-stdlib=libc++")
    else()
        # nothing special for gcc at the moment
    endif()
endif()
And yes, you don't explicitly specify the C++ standard anymore, you just name the C++ feature your code/target does depend on with target_compile_features() calls.
For this example I've chosen cxx_lambda_init_captures which would for e.g. an older GCC compiler give the following error (as an example what happens if a compiler does not support this feature):
The compiler feature "cxx_lambda_init_captures" is not known to CXX compiler
"GNU"
version 4.8.4.
And you need to write a wrapper script to build multiple configurations with a "single configuration" makefile generator or use a "multi configuration" IDE as Visual Studio.
Here are the references to examples:
So I've tested the following with the Open Folder Visual Studio 2017 CMake support to combine in this example the cl, clang and mingw compilers:

CMakeSettings.json
{
    // See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
    "configurations": [
        {
            "name": "x86-Debug",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Debug",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "x86-Release",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Release",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "Clang-Debug",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Debug",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "cmakeCommandArgs": "-T\"LLVM-vs2014\"",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "Clang-Release",
            "generator": "Visual Studio 15 2017",
            "configurationType": "Release",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "cmakeCommandArgs": "-T\"LLVM-vs2014\"",
            "buildCommandArgs": "-m -v:minimal",
        },
        {
            "name": "GNU-Debug",
            "generator": "MinGW Makefiles",
            "configurationType": "Debug",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "variables": [
                {
                    "name": "CMAKE_MAKE_PROGRAM",
                    "value": "${projectDir}\\mingw32-make.cmd"
                }
            ]
        },
        {
            "name": "GNU-Release",
            "generator": "Unix Makefiles",
            "configurationType": "Release",
            "buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
            "variables": [
                {
                    "name": "CMAKE_MAKE_PROGRAM",
                    "value": "${projectDir}\\mingw32-make.cmd"
                }
            ]
        }
    ]
}
mingw32-make.cmd
@echo off
mingw32-make.exe %~1 %~2 %~3 %~4
So you can use any CMake generator from within Visual Studio 2017, there is some unhealthy quoting going on (as for September 2017, maybe fixed later) that requires that mingw32-make.cmd intermediator (removing the quotes).