diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7a39496e741c244e6998df28fb26b4d1d1afe5fd..c138a81876b7377d8e4ed48a3aa9f163b8586552 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -139,6 +139,9 @@ endif()
 
 ############################################################################################################################
 
+set( CMAKE_CXX_STANDARD 14 )
+set( CMAKE_CXX_STANDARD_REQUIRED ON )
+set( CMAKE_CXX_EXTENSIONS OFF )
 
 ############################################################################################################################
 ##
@@ -172,7 +175,7 @@ if( CMAKE_CXX_COMPILER MATCHES "icpc" OR CMAKE_CXX_COMPILER_ARG1 MATCHES "icpc"
     MARK_AS_ADVANCED(XILD)
     if( CMAKE_VERSION VERSION_LESS 3.6.0 )
       set( CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14" )
-      add_flag ( CMAKE_CXX_FLAGS ${CMAKE_CXX14_STANDARD_COMPILE_OPTION} )
+      add_flag ( CMAKE_CXX_FLAGS ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
     endif()
 else()
     option ( WALBERLA_CXX_COMPILER_IS_INTEL "Use Intel compiler" OFF  )
@@ -278,10 +281,6 @@ if ( WALBERLA_PROFILE_USE )
     endif()
 endif()
 
-set( CMAKE_CXX_STANDARD 14 )
-set( CMAKE_CXX_STANDARD_REQUIRED ON )
-set( CMAKE_CXX_EXTENSIONS OFF )
-
 # common flags for intel and g++
 if ( NOT WARNING_DISABLE AND ( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_INTEL ) )
    add_flag ( CMAKE_CXX_FLAGS "-Wall -Wconversion -Wshadow" )
@@ -290,7 +289,7 @@ endif()
 # C++ language features for NEC compiler
 if( WALBERLA_CXX_COMPILER_IS_NEC )
    set( CMAKE_CXX14_STANDARD_COMPILE_OPTION "-Kcpp14" )
-   add_flag ( CMAKE_CXX_FLAGS "${CMAKE_CXX14_STANDARD_COMPILE_OPTION} -Krtti -Kexceptions -size_t64 -Kgcc" )
+   add_flag ( CMAKE_CXX_FLAGS "${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} -Krtti -Kexceptions -size_t64 -Kgcc" )
    add_flag ( CMAKE_CXX_FLAGS "-D__BIG_ENDIAN -D__BYTE_ORDER=__BIG_ENDIAN" )
    add_flag ( CMAKE_CXX_FLAGS "-Tnoauto,used" )
    add_flag ( CMAKE_EXE_LINKER_FLAGS "-Wl,-h,muldefs" )
@@ -442,19 +441,19 @@ endif()
 ############################################################################################################################
 
 try_compile( WALBERLA_USE_STD_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp"
-             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_FILESYSTEM ${CMAKE_CXX14_STANDARD_COMPILE_OPTION} )
+             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
 if( WALBERLA_USE_STD_FILESYSTEM )
    message( STATUS "Found std::filesystem")
 else()
    try_compile( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp"
-                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX14_STANDARD_COMPILE_OPTION} )
+                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
    if( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM )
       message( STATUS "Found std::experimental::filesystem")
    endif()
    if( NOT WALBERLA_CXX_COMPILER_IS_MSVC AND NOT WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM )
       unset( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM CACHE )
       try_compile( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp"
-                   COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX14_STANDARD_COMPILE_OPTION}
+                   COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION}
                    LINK_LIBRARIES stdc++fs )
       if( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM )
          message( STATUS "Found std::experimental::filesystem in libstdc++fs")
@@ -464,7 +463,7 @@ else()
    if( NOT WALBERLA_CXX_COMPILER_IS_MSVC AND NOT WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM )
       unset( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM CACHE )
       try_compile( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp"
-                   COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX14_STANDARD_COMPILE_OPTION}
+                   COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION}
                    LINK_LIBRARIES c++experimental )
       if( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM )
          message( STATUS "Found std::experimental::filesystem in libc++experimental")
@@ -474,29 +473,35 @@ else()
 endif()
 
 try_compile( WALBERLA_USE_STD_ANY "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdAny.cpp"
-             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_ANY ${CMAKE_CXX14_STANDARD_COMPILE_OPTION} )
+             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_ANY ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
 if( WALBERLA_USE_STD_ANY )
    message( STATUS "Found std::any")
 else()
    try_compile( WALBERLA_USE_STD_EXPERIMENTAL_ANY "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdAny.cpp"
-                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_ANY ${CMAKE_CXX14_STANDARD_COMPILE_OPTION} )
+                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_ANY ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
    if( WALBERLA_USE_STD_EXPERIMENTAL_ANY )
       message( STATUS "Found std::experimental::any")
    endif()
 endif()
 
 try_compile( WALBERLA_USE_STD_OPTIONAL "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdOptional.cpp"
-             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_OPTIONAL ${CMAKE_CXX14_STANDARD_COMPILE_OPTION} )
+             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_OPTIONAL ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
 if( WALBERLA_USE_STD_OPTIONAL )
    message( STATUS "Found std::optional")
 else()
    try_compile( WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdOptional.cpp"
-                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL ${CMAKE_CXX14_STANDARD_COMPILE_OPTION} )
+                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
    if( WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL )
       message( STATUS "Found std::experimental::optional")
    endif()
 endif()
 
+try_compile( WALBERLA_USE_STD_VARIANT "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdVariant.cpp"
+             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_VARIANT ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} )
+if( WALBERLA_USE_STD_VARIANT )
+   message( STATUS "Found std::variant")
+endif()
+
 
 
 ############################################################################################################################
@@ -1126,7 +1131,7 @@ if ( WALBERLA_BUILD_WITH_CUDA )
         endif()
 
         if ( NOT "${CUDA_NVCC_FLAGS}" MATCHES "-std=" AND NOT WALBERLA_CXX_COMPILER_IS_MSVC )
-            list ( APPEND CUDA_NVCC_FLAGS "-std=c++14" )
+            list ( APPEND CUDA_NVCC_FLAGS "-std=c++${CMAKE_CXX_STANDARD}" )
         endif ()
 
         if(CMAKE_BUILD_TYPE MATCHES Debug)
diff --git a/cmake/TestStdAny.cpp b/cmake/TestStdAny.cpp
index 6b7e22269737d293cab1daba5d4030c186b5fcd8..6bcc880a6134bf1c0c538f6a32e92f87f6d1e8ea 100644
--- a/cmake/TestStdAny.cpp
+++ b/cmake/TestStdAny.cpp
@@ -8,9 +8,10 @@
 int main() {
 #if defined(WALBERLA_USE_STD_ANY)
    auto a = std::any(42);
+   std::cout << std::any_cast<int>(a) << std::endl;
 #elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY)
    auto a = std::experimental::any(42);
-#endif
    std::cout << std::experimental::any_cast<int>(a) << std::endl;
+#endif
    return 0;
 }
diff --git a/cmake/TestStdVariant.cpp b/cmake/TestStdVariant.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..be98d121ffcfbc96d73948fee5ed67e0f75e8256
--- /dev/null
+++ b/cmake/TestStdVariant.cpp
@@ -0,0 +1,7 @@
+#include <iostream>
+#include <variant>
+
+int main() {
+   std::variant<int,float> a;
+   return 0;
+}
diff --git a/src/core/Variant.h b/src/core/Variant.h
new file mode 100644
index 0000000000000000000000000000000000000000..7fe6d195afcacf49b0c1dea05d14edc61d0b408d
--- /dev/null
+++ b/src/core/Variant.h
@@ -0,0 +1,58 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) OPTIONAL later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  OPTIONAL WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file Variant.h
+//! \ingroup core
+//! \author Stephan Seitz <stephan.seitz@fau.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+
+#if defined(WALBERLA_USE_STD_VARIANT)
+#include <variant>
+#else
+#include <boost/variant.hpp>
+#endif
+
+
+
+namespace walberla
+{
+
+#if defined(WALBERLA_USE_STD_VARIANT)
+using std::variant;
+using std::visit;
+using std::get;
+using std::holds_alternative;
+using std::bad_variant_access;
+#else
+using boost::variant;
+using boost::get;
+template <class T, class... Types>
+constexpr bool holds_alternative( const boost::variant<Types...>& v ) noexcept
+{
+   return v.type() == typeid( T );
+}
+using bad_variant_access = boost::bad_get;
+template<typename Visitor, typename... Variant>
+decltype( auto ) visit( Visitor&& visitor, Variant&& ... variant )
+{
+   return boost::apply_visitor( visitor, variant... );
+}
+#endif
+
+}
diff --git a/src/waLBerlaDefinitions.in.h b/src/waLBerlaDefinitions.in.h
index bb9b6d029d80340f34342401a23d2f13e2356b7d..654eb55ab235a5a583099cdbcfedb46e1844297a 100644
--- a/src/waLBerlaDefinitions.in.h
+++ b/src/waLBerlaDefinitions.in.h
@@ -53,6 +53,7 @@
 #cmakedefine WALBERLA_USE_STD_ANY
 #cmakedefine WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL
 #cmakedefine WALBERLA_USE_STD_OPTIONAL
+#cmakedefine WALBERLA_USE_STD_VARIANT
 #cmakedefine WALBERLA_BUILD_WITH_BACKTRACE
 #ifdef WALBERLA_BUILD_WITH_BACKTRACE
 #define WALBERLA_BACKTRACE_HEADER "${Backtrace_HEADER}"
diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt
index 185fc8be096a4d357d6a6f64225d4cdc6ffe637c..4d58647b8a563af3a86f01183f226136f835427f 100644
--- a/tests/core/CMakeLists.txt
+++ b/tests/core/CMakeLists.txt
@@ -209,6 +209,11 @@ waLBerla_execute_test( NAME UNIQUEID PROCESSES 4)
 waLBerla_compile_test( FILES VersionTest.cpp )
 waLBerla_execute_test( NAME VersionTest )
 
+if( WALBERLA_BUILD_WITH_BOOST OR WALBERLA_USE_STD_VARIANT )
+  waLBerla_compile_test( FILES VariantTest )
+  waLBerla_execute_test( NAME VariantTest )
+endif()
+
 ##################
 # load_balancing #
 ##################
diff --git a/tests/core/VariantTest.cpp b/tests/core/VariantTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a879b5b98a7020a93f51bcb20ea1baf952a97eba
--- /dev/null
+++ b/tests/core/VariantTest.cpp
@@ -0,0 +1,81 @@
+//======================================================================================================================
+//
+//  This file is part of waLBerla. waLBerla is free software: you can
+//  redistribute it and/or modify it under the terms of the GNU General Public
+//  License as published by the Free Software Foundation, either version 3 of
+//  the License, or (at your option) any later version.
+//
+//  waLBerla is distributed in the hope that it will be useful, but WITHOUT
+//  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+//  for more details.
+//
+//  You should have received a copy of the GNU General Public License along
+//  with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>.
+//
+//! \file VariantTest.cpp
+//! \ingroup core
+//! \author Step
+//! \brief Test if there are no typos in the collective header files "all.h"
+//
+//======================================================================================================================
+
+#include "core/Variant.h"
+#include "core/debug/all.h"
+
+#include <string>
+#include <cassert>
+#include <iostream>
+#include <vector>
+
+using namespace std::literals; // C++ 14
+using var_t = walberla::variant<int, long, double, std::string>;
+
+int main( int /*argc*/, char** /*argv*/ )
+{
+   walberla::debug::enterTestMode();
+
+
+
+   // Example from: https://en.cppreference.com/w/cpp/utility/variant (license (CC-BY-SA) and GPL)
+   walberla::variant<int, float> v, w;
+   v = 12; // v contains int
+   int i = walberla::get<int>( v );
+#ifdef WALBERLA_USE_STD_VARIANT
+   WALBERLA_CHECK( i == 12 ); // boost::variant cannot use == with variant and type
+#endif
+   WALBERLA_CHECK( 0 == 12 - i );
+   w = walberla::get<int>( v );
+   w = v;
+#ifdef WALBERLA_USE_STD_VARIANT
+   WALBERLA_CHECK( w == 12 ); // boost::variant cannot use == with variant and type
+#endif
+   WALBERLA_CHECK( 0 == 12 - i );
+
+   //  walberla::get<double>(v); // error: no double in [int, float]
+   //  walberla::get<3>(v);      // error: valid index values are 0 and 1
+
+   try {
+      walberla::get<float>( w ); // w contains int, not float: will throw
+   } catch ( const walberla::bad_variant_access& ) {}
+
+   walberla::variant<std::string> x( "abc" ); // converting constructors work when unambiguous
+   x = "def"; // converting assignment also works when unambiguous
+
+   std::cout << "hallo" << std::endl;
+   walberla::variant<std::string, bool> y( "abc" ); // casts to bool when passed a char const *
+   std::cout << "eoo" << std::endl;
+   WALBERLA_CHECK( walberla::holds_alternative<bool>( y ) ); // succeeds
+   y = "xyz"s;
+   WALBERLA_CHECK( walberla::holds_alternative<std::string>( y ) ); //succeeds
+
+   std::cout << "bye" << std::endl;
+   std::vector<var_t> vec {10, 15l, 1.5, "hello"};
+
+   for ( auto& z : vec ) {
+      // 1. void visitor, only called for side-effects (here, for I/O)
+      walberla::visit( []( auto && arg ) {std::cout << arg;}, z );
+   }
+
+   return 0;
+}