Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:54:04

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