From 9a897e23eec25814f7850c4c423485ab37496739 Mon Sep 17 00:00:00 2001
From: Michael Kuron <mkuron@icp.uni-stuttgart.de>
Date: Wed, 31 Jan 2018 14:15:41 +0100
Subject: [PATCH] [API] Remove boost::any and boost::optional

API changes in blockforest::PhantomBlockForest, blockforest::loadbalancing, pe::amr::weight_assignment
mpi can now only send/receive walberla::optional instead of boost::optional
---
 CMakeLists.txt                                | 24 ++++++++++
 .../SchaeferTurek/SchaeferTurek.cpp           |  4 +-
 cmake/TestStdAny.cpp                          | 16 +++++++
 cmake/TestStdOptional.cpp                     | 19 ++++++++
 src/blockforest/PhantomBlock.h                |  7 ++-
 src/blockforest/PhantomBlockForest.cpp        |  6 +--
 src/blockforest/PhantomBlockForest.h          |  4 +-
 .../loadbalancing/DynamicParMetis.h           |  2 +-
 .../loadbalancing/PODPhantomData.h            |  2 +-
 src/core/Any.h                                | 48 +++++++++++++++++++
 src/core/Optional.h                           | 48 +++++++++++++++++++
 src/core/mpi/BufferDataTypeExtensions.h       | 12 ++---
 .../MetisAssignmentFunctor.h                  |  2 +-
 .../WeightAssignmentFunctor.h                 |  2 +-
 src/waLBerlaDefinitions.in.h                  |  4 ++
 tests/core/mpi/BufferTest.cpp                 |  4 +-
 16 files changed, 181 insertions(+), 23 deletions(-)
 create mode 100644 cmake/TestStdAny.cpp
 create mode 100644 cmake/TestStdOptional.cpp
 create mode 100644 src/core/Any.h
 create mode 100644 src/core/Optional.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b579381c6..14c5d015f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -474,6 +474,30 @@ else()
    endif()
 endif()
 
+try_compile( WALBERLA_USE_STD_ANY "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/cmake/TestStdAny.cpp"
+             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_ANY -std=c++14 )
+if( WALBERLA_USE_STD_ANY )
+   message( STATUS "Found std::any")
+else()
+   try_compile( WALBERLA_USE_STD_EXPERIMENTAL_ANY "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/cmake/TestStdAny.cpp"
+                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_ANY -std=c++14 )
+   if( WALBERLA_USE_STD_EXPERIMENTAL_ANY )
+      message( STATUS "Found std::experimental::any")
+   endif()
+endif()
+
+try_compile( WALBERLA_USE_STD_OPTIONAL "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/cmake/TestStdOptional.cpp"
+             COMPILE_DEFINITIONS -DWALBERLA_USE_STD_OPTIONAL -std=c++14 )
+if( WALBERLA_USE_STD_OPTIONAL )
+   message( STATUS "Found std::optional")
+else()
+   try_compile( WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/cmake/TestStdOptional.cpp"
+                COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL -std=c++14 )
+   if( WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL )
+      message( STATUS "Found std::experimental::optional")
+   endif()
+endif()
+
 
 
 ############################################################################################################################
diff --git a/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp b/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp
index 695cc61f6..ed907fc37 100644
--- a/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp
+++ b/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp
@@ -1285,7 +1285,7 @@ public:
       markEmptyBlocks_( markEmptyBlocks ), state_( state )
    {}
    
-   void operator()( std::vector< std::pair< const PhantomBlock *, boost::any > > & blockData, const PhantomBlockForest & )
+   void operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, const PhantomBlockForest & )
    {
       for( auto it = blockData.begin(); it != blockData.end(); ++it )
       {
@@ -1309,7 +1309,7 @@ struct Pseudo2DPhantomWeightPackUnpack
       buffer << block.getData< Pseudo2DPhantomWeight >().weight();
    }
 
-   void operator()( mpi::RecvBuffer & buffer, const PhantomBlock &, boost::any & data )
+   void operator()( mpi::RecvBuffer & buffer, const PhantomBlock &, walberla::any & data )
    {
       Pseudo2DPhantomWeight::weight_t w;
       buffer >> w;
diff --git a/cmake/TestStdAny.cpp b/cmake/TestStdAny.cpp
new file mode 100644
index 000000000..6b7e22269
--- /dev/null
+++ b/cmake/TestStdAny.cpp
@@ -0,0 +1,16 @@
+#include <iostream>
+#if defined(WALBERLA_USE_STD_ANY)
+#include <any>
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY)
+#include <experimental/any>
+#endif
+
+int main() {
+#if defined(WALBERLA_USE_STD_ANY)
+   auto a = std::any(42);
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY)
+   auto a = std::experimental::any(42);
+#endif
+   std::cout << std::experimental::any_cast<int>(a) << std::endl;
+   return 0;
+}
diff --git a/cmake/TestStdOptional.cpp b/cmake/TestStdOptional.cpp
new file mode 100644
index 000000000..fc3a148c1
--- /dev/null
+++ b/cmake/TestStdOptional.cpp
@@ -0,0 +1,19 @@
+#include <iostream>
+#if defined(WALBERLA_USE_STD_OPTIONAL)
+#include <optional>
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL)
+#include <experimental/optional>
+#endif
+
+int main() {
+#if defined(WALBERLA_USE_STD_OPTIONAL)
+   auto a = std::optional<int>();
+   auto b = std::optional<int>(42);
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL)
+   auto a = std::experimental::optional<int>();
+   auto b = std::experimental::optional<int>(42);
+#endif
+   if (b)
+      std::cout << a.value_or(b.value()) << std::endl;
+   return 0;
+}
diff --git a/src/blockforest/PhantomBlock.h b/src/blockforest/PhantomBlock.h
index a209e1a17..7f42061ab 100644
--- a/src/blockforest/PhantomBlock.h
+++ b/src/blockforest/PhantomBlock.h
@@ -28,11 +28,10 @@
 #include "core/debug/Debug.h"
 #include "core/math/AABB.h"
 #include "core/uid/SUID.h"
+#include "core/Any.h"
 
 #include <vector>
 
-#include <boost/any.hpp>
-
 
 
 namespace walberla {
@@ -86,7 +85,7 @@ public:
    void addData( const T & data ) { data_ = data; }
    
    template< typename T >
-   T getData() const { return boost::any_cast<T>( data_ ); }
+   T getData() const { return walberla::any_cast<T>( data_ ); }
    
    bool hasData() const { return !(data_.empty()); }
    
@@ -143,7 +142,7 @@ private:
    uint_t level_;
 
    // set by the user/application via callback
-   boost::any data_;
+   walberla::any data_;
 
    std::vector< NeighborBlock* > neighborhoodSection_[26]; // the 26 neighborhood sections (can be restored from 'neighborhood_')
    std::vector< NeighborBlock  > neighborhood_;            // all neighbor blocks
diff --git a/src/blockforest/PhantomBlockForest.cpp b/src/blockforest/PhantomBlockForest.cpp
index 691cfe744..196ba5529 100644
--- a/src/blockforest/PhantomBlockForest.cpp
+++ b/src/blockforest/PhantomBlockForest.cpp
@@ -256,13 +256,13 @@ void PhantomBlockForest::assignBlockData( const PhantomBlockDataAssignmentFuncti
 {
    if( function )
    {
-      std::vector< std::pair< const PhantomBlock *, boost::any > > blockData;
+      std::vector< std::pair< const PhantomBlock *, walberla::any > > blockData;
    
       for( auto it = blocks_.begin(); it != blocks_.end(); ++it )
       {
          auto & block = it->second;
          WALBERLA_ASSERT_NOT_NULLPTR( block.get() );
-         blockData.push_back( std::make_pair( block.get(), boost::any() ) );
+         blockData.push_back( std::make_pair( block.get(), walberla::any() ) );
       }
       
       function( blockData, *this );
@@ -484,7 +484,7 @@ void PhantomBlockForest::migrate( const PhantomBlockDataPackFunction & packBlock
          if( unpackBlockData )
          {
             WALBERLA_ASSERT( static_cast<bool>(packBlockData) );
-            boost::any data;
+            walberla::any data;
             unpackBlockData( buffer, *phantom, data );
             phantom->addData( data );
          }
diff --git a/src/blockforest/PhantomBlockForest.h b/src/blockforest/PhantomBlockForest.h
index 797a29cbe..1c7285167 100644
--- a/src/blockforest/PhantomBlockForest.h
+++ b/src/blockforest/PhantomBlockForest.h
@@ -45,7 +45,7 @@ public:
    typedef std::function< Set<SUID> ( const std::vector< std::pair< BlockID, Set<SUID> > > & source, const BlockID & destintation ) >
            BlockStateDeterminationFunction;
 
-   typedef std::function< void ( std::vector< std::pair< const PhantomBlock *, boost::any > > & blockData,
+   typedef std::function< void ( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData,
                                    const PhantomBlockForest & phantomForest ) >
            PhantomBlockDataAssignmentFunction;
 
@@ -58,7 +58,7 @@ public:
            MigrationPreparationFunction; // = load balancing
 
    typedef std::function< void ( mpi::SendBuffer & buffer, const PhantomBlock & block ) >                    PhantomBlockDataPackFunction;
-   typedef std::function< void ( mpi::RecvBuffer & buffer, const PhantomBlock & block, boost::any & data ) > PhantomBlockDataUnpackFunction;
+   typedef std::function< void ( mpi::RecvBuffer & buffer, const PhantomBlock & block, walberla::any & data ) > PhantomBlockDataUnpackFunction;
 
 
 
diff --git a/src/blockforest/loadbalancing/DynamicParMetis.h b/src/blockforest/loadbalancing/DynamicParMetis.h
index 1fa7667ee..927ca2569 100644
--- a/src/blockforest/loadbalancing/DynamicParMetis.h
+++ b/src/blockforest/loadbalancing/DynamicParMetis.h
@@ -119,7 +119,7 @@ struct DynamicParMetisBlockInfoPackUnpack
       block.getData< DynamicParMetisBlockInfo >().toBuffer( buffer );
    }
 
-   void operator()( mpi::RecvBuffer & buffer, const PhantomBlock &, boost::any & data )
+   void operator()( mpi::RecvBuffer & buffer, const PhantomBlock &, walberla::any & data )
    {
       data = DynamicParMetisBlockInfo( buffer );
    }
diff --git a/src/blockforest/loadbalancing/PODPhantomData.h b/src/blockforest/loadbalancing/PODPhantomData.h
index ccf514a1f..2be8c77ce 100644
--- a/src/blockforest/loadbalancing/PODPhantomData.h
+++ b/src/blockforest/loadbalancing/PODPhantomData.h
@@ -53,7 +53,7 @@ struct PODPhantomWeightPackUnpack
       buffer << block.getData< PODPhantomWeight<T> >().weight();
    }
 
-   void operator()( mpi::RecvBuffer & buffer, const PhantomBlock &, boost::any & data )
+   void operator()( mpi::RecvBuffer & buffer, const PhantomBlock &, walberla::any & data )
    {
       typename PODPhantomWeight<T>::weight_t w;
       buffer >> w;
diff --git a/src/core/Any.h b/src/core/Any.h
new file mode 100644
index 000000000..2799c1e85
--- /dev/null
+++ b/src/core/Any.h
@@ -0,0 +1,48 @@
+//======================================================================================================================
+//
+//  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 Any.h
+//! \ingroup core
+//! \author Michael Kuron <mkuron@icp.uni-stuttgart.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+
+#if defined(WALBERLA_USE_STD_ANY)
+#include <any>
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY)
+#include <experimental/any>
+#else
+#include <boost/any.hpp>
+#endif
+
+
+
+namespace walberla {
+
+#if defined(WALBERLA_USE_STD_ANY)
+using std::any;
+using std::any_cast;
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY)
+using std::experimental::any;
+using std::experimental::any_cast;
+#else
+using boost::any;
+using boost::any_cast;
+#endif
+
+}
diff --git a/src/core/Optional.h b/src/core/Optional.h
new file mode 100644
index 000000000..ad23d1666
--- /dev/null
+++ b/src/core/Optional.h
@@ -0,0 +1,48 @@
+//======================================================================================================================
+//
+//  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 Optional.h
+//! \ingroup core
+//! \author Michael Kuron <mkuron@icp.uni-stuttgart.de>
+//
+//======================================================================================================================
+
+#pragma once
+
+
+#if defined(WALBERLA_USE_STD_OPTIONAL)
+#include <optional>
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL)
+#include <experimental/optional>
+#else
+#include <boost/optional.hpp>
+#endif
+
+
+
+namespace walberla {
+
+#if defined(WALBERLA_USE_STD_OPTIONAL)
+using std::optional;
+using std::nullopt;
+#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL)
+using std::experimental::optional;
+using std::experimental::nullopt;
+#else
+using boost::optional;
+const boost::none_t nullopt = boost::none;
+#endif
+
+}
diff --git a/src/core/mpi/BufferDataTypeExtensions.h b/src/core/mpi/BufferDataTypeExtensions.h
index 47d22baca..b05128c4a 100644
--- a/src/core/mpi/BufferDataTypeExtensions.h
+++ b/src/core/mpi/BufferDataTypeExtensions.h
@@ -27,10 +27,10 @@
 #include "SendBuffer.h"
 #include "core/Conversion.h"
 #include "core/DataTypes.h"
+#include "core/Optional.h"
 
 #include <boost/array.hpp>
 #include <boost/integer.hpp>
-#include <boost/optional.hpp>
 #include <boost/uuid/uuid.hpp>
 
 #include <deque>
@@ -465,18 +465,18 @@ struct BufferSizeTrait< std::multimap<K,T,C,A> > { static const bool constantSiz
 
 
 // ---------------------------------------------------------------------------------------------------------------------
-// ------------------------------------- Boost optional Support --------------------------------------------------------
+// ------------------------------------------- optional Support --------------------------------------------------------
 // ---------------------------------------------------------------------------------------------------------------------
 
 template< typename T,    // Element type of SendBuffer
           typename G,    // Growth policy of SendBuffer
           typename OT>   // Optional type
-GenericSendBuffer<T,G>& operator<<( GenericSendBuffer<T,G> & buf, const boost::optional<OT> & o )
+GenericSendBuffer<T,G>& operator<<( GenericSendBuffer<T,G> & buf, const walberla::optional<OT> & o )
 {
    buf.addDebugMarker( "op" );
 
    bool hasContent = true;
-   if (o == boost::none)
+   if (o == walberla::nullopt)
       hasContent = false;
 
    buf << hasContent;
@@ -489,7 +489,7 @@ GenericSendBuffer<T,G>& operator<<( GenericSendBuffer<T,G> & buf, const boost::o
 
 template< typename T,    // Element type of RecvBuffer
           typename OT>   // Optional type
-GenericRecvBuffer<T>& operator>>( GenericRecvBuffer<T> & buf, boost::optional<OT> & o )
+GenericRecvBuffer<T>& operator>>( GenericRecvBuffer<T> & buf, walberla::optional<OT> & o )
 {
    buf.readDebugMarker( "op" );
 
@@ -509,7 +509,7 @@ GenericRecvBuffer<T>& operator>>( GenericRecvBuffer<T> & buf, boost::optional<OT
    }
    else
    {
-      o = boost::none;
+      o = walberla::nullopt;
    }
 
    return buf;
diff --git a/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h b/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h
index 3b03af49e..bed286166 100644
--- a/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h
+++ b/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h
@@ -38,7 +38,7 @@ public:
    MetisAssignmentFunctor( const shared_ptr<InfoCollection>& ic ) : ic_( ic )
    {}
 
-   void operator()( std::vector< std::pair< const PhantomBlock *, boost::any > > & blockData, const PhantomBlockForest & )
+   void operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, const PhantomBlockForest & )
    {
       for( auto it = blockData.begin(); it != blockData.end(); ++it )
       {
diff --git a/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h b/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h
index 3a6b5d9b2..a2cd0fc06 100644
--- a/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h
+++ b/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h
@@ -40,7 +40,7 @@ public:
 
    WeightAssignmentFunctor( shared_ptr<InfoCollection>& ic ) : ic_(ic) {}
 
-   void operator()( std::vector< std::pair< const PhantomBlock *, boost::any > > & blockData, const PhantomBlockForest & )
+   void operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, const PhantomBlockForest & )
    {
       for( auto it = blockData.begin(); it != blockData.end(); ++it )
       {
diff --git a/src/waLBerlaDefinitions.in.h b/src/waLBerlaDefinitions.in.h
index 703bee6fc..26b662768 100644
--- a/src/waLBerlaDefinitions.in.h
+++ b/src/waLBerlaDefinitions.in.h
@@ -44,6 +44,10 @@
 
 #cmakedefine WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM
 #cmakedefine WALBERLA_USE_STD_FILESYSTEM
+#cmakedefine WALBERLA_USE_STD_EXPERIMENTAL_ANY
+#cmakedefine WALBERLA_USE_STD_ANY
+#cmakedefine WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL
+#cmakedefine WALBERLA_USE_STD_OPTIONAL
 
 // SIMD
 #cmakedefine WALBERLA_SIMD_FORCE_SCALAR
diff --git a/tests/core/mpi/BufferTest.cpp b/tests/core/mpi/BufferTest.cpp
index 34f961f1a..c34a1ef8e 100644
--- a/tests/core/mpi/BufferTest.cpp
+++ b/tests/core/mpi/BufferTest.cpp
@@ -263,7 +263,7 @@ void bufferTestUInt8()
 {
    std::string stdString("Hello World!"), stdStringEmpty;
 
-   boost::optional<int> optional0, optional1, optional2, optional3;
+   walberla::optional<int> optional0, optional1, optional2, optional3;
    optional2 = 23;
    optional3 = 42;
 
@@ -277,7 +277,7 @@ void bufferTestUInt8()
 
    std::string recvStdString, recvStdStringEmpty;
 
-   boost::optional<int> recvOptional0, recvOptional1, recvOptional2, recvOptional3;
+   walberla::optional<int> recvOptional0, recvOptional1, recvOptional2, recvOptional3;
 
    recvOptional0 = 123;
    recvOptional1 = 123;
-- 
GitLab