Program Listing for File particle_traits.hpp

Return to documentation for file (include/beluga/type_traits/particle_traits.hpp)

// Copyright 2022-2024 Ekumen, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef BELUGA_TYPE_TRAITS_PARTICLE_TRAITS_HPP
#define BELUGA_TYPE_TRAITS_PARTICLE_TRAITS_HPP

#include <beluga/primitives.hpp>
#include <beluga/type_traits/tuple_traits.hpp>
#include <range/v3/range/traits.hpp>

namespace beluga {

template <class T>
struct particle_traits {
  using state_type = std::decay_t<decltype(beluga::state(std::declval<T>()))>;
  using weight_type = std::decay_t<decltype(beluga::weight(std::declval<T>()))>;
};

template <class T>
using state_t = typename particle_traits<T>::state_type;

template <class T>
using weight_t = typename particle_traits<T>::weight_type;


template <class T, class = void>
struct has_state : public std::false_type {};

template <class T>
struct has_state<T, std::void_t<decltype(beluga::state(std::declval<T>()))>> : std::true_type {};

template <class T>
inline constexpr bool has_state_v = has_state<T>::value;

template <class T, class = void>
struct has_weight : public std::false_type {};

template <class T>
struct has_weight<T, std::void_t<decltype(beluga::weight(std::declval<T>()))>> : std::true_type {};

template <class T>
inline constexpr bool has_weight_v = has_weight<T>::value;

template <class T, class = void>
struct is_particle : public std::false_type {};

template <class T>
struct is_particle<T, std::enable_if_t<std::conjunction_v<has_state<T>, has_weight<T>>>> : std::true_type {};

template <class T>
inline constexpr bool is_particle_v = is_particle<T>::value;

template <class R>
inline constexpr bool is_particle_range_v = is_particle_v<ranges::range_value_t<R>>;


namespace detail {

template <class Particle, class State = state_t<Particle>>
struct make_from_state_fn {

  constexpr auto operator()(State value) const {
    static_assert(is_particle_v<Particle>);
    auto particle = []() {
      if constexpr (is_tuple_like_v<Particle>) {
        // Support for zipped ranges composed with views that don't
        // propagate the tuple value type of the original range
        // (ranges::views::const_).
        return decay_tuple_like_t<Particle>{};
      } else {
        return Particle{};
      }
    }();
    beluga::state(particle) = std::move(value);
    beluga::weight(particle) = 1.0;
    return particle;
  }
};

}  // namespace detail


template <class Particle>
inline constexpr detail::make_from_state_fn<Particle> make_from_state;

}  // namespace beluga

#endif