Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:46

0001 //----------------------------------*-C++-*----------------------------------//
0002 // Copyright 2023-2024 UT-Battelle, LLC, and other Celeritas developers.
0003 // See the top-level COPYRIGHT file for details.
0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0005 //---------------------------------------------------------------------------//
0006 //! \file corecel/cont/VariantUtils.hh
0007 //! \brief Host-only utilities for use with std::variant
0008 //---------------------------------------------------------------------------//
0009 #pragma once
0010 
0011 #include <type_traits>
0012 #include <utility>
0013 
0014 #include "corecel/Assert.hh"
0015 
0016 #include "detail/VariantUtilsImpl.hh"
0017 
0018 namespace celeritas
0019 {
0020 //---------------------------------------------------------------------------//
0021 /*!
0022  * Helper class for dispatching type-specific lambdas.
0023  *
0024  * Example applied to a variant that converts to int or string: \code
0025   std::visit(Overload{[](int a) { cout << a + 2; },
0026                       [](std::string const& s) { cout << '"' << s << '"'; }},
0027              my_variant);
0028  * \endcode
0029  */
0030 template<typename... Ts>
0031 struct Overload : Ts...
0032 {
0033     using Ts::operator()...;
0034 };
0035 
0036 // Template deduction guide
0037 template<class... Ts>
0038 Overload(Ts&&...) -> Overload<Ts...>;
0039 
0040 //---------------------------------------------------------------------------//
0041 /*!
0042  * Create a wrapper functor for unifying the return type.
0043  *
0044  * This provides a unified return type \c T (usually a variant) that can be
0045  * implicitly constructed from all return types of a functor \c F that operates
0046  * on a generic type \c U . The class is necessary because \c std::visit
0047  * requires all return types to be the same.
0048  *
0049  * Example: \code
0050    std::visit(return_as<VariantTransform>(Translate{{1,2,3}}), value);
0051  \endcode
0052  */
0053 template<class T, class F>
0054 detail::ReturnAsImpl<T, F> return_as(F&& func)
0055 {
0056     return {std::forward<F>(func)};
0057 }
0058 
0059 //---------------------------------------------------------------------------//
0060 /*!
0061  * Define a variant that contains all the classes mapped by an enum+traits.
0062  *
0063  * For example: \code
0064     using VariantSurface = EnumVariant<SurfaceType, SurfaceTypeTraits>;
0065  * \endcode
0066  * is equivalent to: \code
0067     using VariantSurface = std::variant<PlaneX, PlaneY, ..., GeneralQuadric>;
0068  * \endcode
0069  *
0070  * \sa EnumClassUtils.hh
0071  */
0072 template<class E, template<E> class ETraits>
0073 using EnumVariant = typename detail::EnumVariantImpl<E, ETraits>::type;
0074 
0075 //---------------------------------------------------------------------------//
0076 /*!
0077  * Visit a container's element by calling "visit" on the corresponding index.
0078  *
0079  * example: \code
0080    std::vector<std::variant<int, std:string>> myvec{"hi", 123, "bye"};
0081    ContainerVisitor visit_element{myvec};
0082    visit_element([](auto&& v) { cout << v; }, 1); // Prints '123'
0083    visit_element([](auto&& v) { cout << v; }, 2); // Prints 'bye'
0084    \endcode
0085  */
0086 template<class T, class U = typename std::remove_reference_t<T>::size_type>
0087 class ContainerVisitor
0088 {
0089   public:
0090     //!@{
0091     //! \name Type aliases
0092     using index_type = U;
0093     //!@}
0094 
0095   public:
0096     //! Construct with a container
0097     explicit ContainerVisitor(T&& container)
0098         : container_{std::forward<T>(container)}
0099     {
0100     }
0101 
0102     //! Visit the functor upon the value at the given index
0103     template<class F>
0104     decltype(auto) operator()(F&& func, U const& idx) const
0105     {
0106         auto&& value = container_[idx];
0107         CELER_ASSUME(!value.valueless_by_exception());
0108         return std::visit(std::forward<F>(func), std::move(value));
0109     }
0110 
0111   private:
0112     T container_;
0113 };
0114 
0115 //---------------------------------------------------------------------------//
0116 // TEMPLATE DEDUCTION
0117 //---------------------------------------------------------------------------//
0118 template<class T>
0119 ContainerVisitor(T&&) -> ContainerVisitor<T>;
0120 
0121 //---------------------------------------------------------------------------//
0122 }  // namespace celeritas