Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Optional based on variantSrc::variant #806

Merged
merged 6 commits into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions include/openPMD/IO/ADIOS/ADIOS2IOHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,20 @@
#pragma once

#include "ADIOS2FilePosition.hpp"
#include "openPMD/config.hpp"
#include "openPMD/IO/AbstractIOHandler.hpp"
#include "openPMD/IO/AbstractIOHandlerImpl.hpp"
#include "openPMD/IO/AbstractIOHandlerImplCommon.hpp"
#include "openPMD/IO/IOTask.hpp"
#include "openPMD/IO/InvalidatableFile.hpp"
#include "openPMD/auxiliary/JSON.hpp"
#include "openPMD/auxiliary/Option.hpp"
#include "openPMD/backend/Writable.hpp"
#include "openPMD/config.hpp"

#if openPMD_HAVE_ADIOS2
# include <adios2.h>
# include "openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp"
# include <adios2.h>

# include "openPMD/IO/ADIOS/ADIOS2Auxiliary.hpp"
#endif

#if openPMD_HAVE_MPI
Expand Down Expand Up @@ -267,7 +269,7 @@ class ADIOS2IOHandlerImpl

// Helper methods.

std::unique_ptr< adios2::Operator >
auxiliary::Option< adios2::Operator >
getCompressionOperator( std::string const & compression );

/*
Expand Down Expand Up @@ -685,7 +687,7 @@ namespace detail
* the C++11 standard
* @todo replace with std::optional upon switching to C++17
*/
std::unique_ptr< adios2::Engine > m_engine;
auxiliary::Option< adios2::Engine > m_engine;
adios2::Mode m_mode;
detail::WriteDataset m_writeDataset;
detail::DatasetReader m_readDataset;
Expand Down Expand Up @@ -745,18 +747,13 @@ namespace detail
* The downside of this is that we need to pay attention to invalidate
* the map whenever an attribute/variable is altered. In that case, we
* fetch the map anew.
* Revisit once https://github.com/openPMD/openPMD-api/issues/563 has
* been resolved
* If false, the buffered map has been invalidated and needs to be
* If empty, the buffered map has been invalidated and needs to be
* queried from ADIOS2 again. If true, the buffered map is equivalent to
* the map that would be returned by a call to
* IO::Available(Attributes|Variables).
*/
bool m_availableAttributesValid = false;
AttributeMap_t m_availableAttributes;

bool m_availableVariablesValid = false;
AttributeMap_t m_availableVariables;
auxiliary::Option< AttributeMap_t > m_availableAttributes;
auxiliary::Option< AttributeMap_t > m_availableVariables;
};


Expand Down
171 changes: 171 additions & 0 deletions include/openPMD/auxiliary/Option.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/* Copyright 2020 Franz Poeschel
*
* This file is part of openPMD-api.
*
* openPMD-api is free software: you can redistribute it and/or modify
* it under the terms of of either the GNU General Public License or
* the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* openPMD-api 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with openPMD-api.
* If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include "VariantSrc.hpp"

#include <utility> // std::forward, std::move


namespace openPMD
{
namespace auxiliary
{
namespace detail
{
struct Empty
{
};
} // namespace detail

/**
* @brief Simple Option type based on variantSrc::variant.
*
* @tparam T Type that can be optionally stored in an Optional object.
*/
template< typename T >
class Option
{
using data_t = variantSrc::variant< T, detail::Empty >;
data_t m_data;

public:
/** Create an empty Option.
*/
explicit Option() : m_data( detail::Empty() )
{
}

/** Create a full Option.
*
* @param data The object to emplace in the Option.
*/
Option( T data ) : m_data( std::move( data ) )
{
}

Option( Option const & other ) = default;

Option &
operator=( Option && other )
{
if( other.has_value() )
{
m_data.template emplace< 0 >( std::move( other.get() ) );
}
else
{
m_data.template emplace< 1 >( detail::Empty() );
}
return *this;
}

Option &
operator=( Option const & other )
{
if( other.has_value() )
{
m_data.template emplace< 0 >( other.get() );
}
else
{
m_data.template emplace< 1 >( detail::Empty() );
}
return *this;
}

bool
operator==( Option const & other ) const
{
if( has_value() )
{
return !other.has_value();
}
else
{
if( !other.has_value() )
{
return false;
}
else
{
return get() == other.get();
}
}
}

bool
operator!=( Option const & other ) const
{
return !( *this == other );
}

/**
* @return Is an object constantly stored in this?
*/
bool
has_value() const
{
return m_data.index() == 0;
}

/**
* @return Is an object constantly stored in this?
*/
operator bool() const
{
return has_value();
}

/**
* @brief Access the emplaced object if one is present.
*
* @throw std::bad_variant_access if no object is present.
* @return The emplaced object.
*/
T const &
get() const
{
return variantSrc::template get< T >( m_data );
}

/**
* @brief Access the emplaced object if one is present.
*
* @throw std::bad_variant_access if no object is present.
* @return The emplaced object.
*/
T &
get()
{
return variantSrc::template get< T >( m_data );
}
};

template< typename T >
Option< T >
makeOption( T && val )
{
return Option< T >( std::forward< T >( val ) );
}
} // namespace auxiliary
} // namespace openPMD
10 changes: 2 additions & 8 deletions include/openPMD/auxiliary/Variant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@
*/
#pragma once

#if __cplusplus >= 201703L
# include <variant> // IWYU pragma: export
namespace variantSrc = std;
#else
# include <mpark/variant.hpp> // IWYU pragma: export
namespace variantSrc = mpark;
#endif
#include "VariantSrc.hpp"

#include <type_traits>

Expand Down Expand Up @@ -79,7 +73,7 @@ class Variant
{
return m_data;
}

/** Retrieve the index of the alternative that is currently been held
*
* @return zero-based index
Expand Down
33 changes: 33 additions & 0 deletions include/openPMD/auxiliary/VariantSrc.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/* Copyright 2002 Axel Huebl
*
* This file is part of openPMD-api.
*
* openPMD-api is free software: you can redistribute it and/or modify
* it under the terms of of either the GNU General Public License or
* the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* openPMD-api 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 and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with openPMD-api.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#if __cplusplus >= 201703L
# include <variant> // IWYU pragma: export
namespace variantSrc = std;
#else
// see: https://github.com/mpark/variant/pull/76
# if defined(__EXCEPTIONS)
# define MPARK_EXCEPTIONS
# endif
# include <mpark/variant.hpp> // IWYU pragma: export
namespace variantSrc = mpark;
#endif
Loading