Program Listing for File primitives.hpp
↰ Return to documentation for file (include/beluga/primitives.hpp
)
// Copyright 2023-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_PRIMITIVES_HPP
#define BELUGA_PRIMITIVES_HPP
#include <tuple>
#include <type_traits>
#include <beluga/type_traits/strongly_typed_numeric.hpp>
#include <beluga/type_traits/tuple_traits.hpp>
#include <beluga/utility/forward_like.hpp>
namespace beluga {
using Weight = Numeric<double, struct WeightTag>;
using Cluster = Numeric<std::size_t, struct ClusterTag>;
namespace state_detail {
template <class T, class = void>
struct has_member_variable_state : std::false_type {};
template <class T>
struct has_member_variable_state<T, std::void_t<decltype(std::declval<T>().state)>> : std::true_type {};
template <class T>
inline constexpr bool has_member_variable_state_v = has_member_variable_state<T>::value;
template <class T, class = void>
struct has_member_state : std::false_type {};
template <class T>
struct has_member_state<T, std::void_t<decltype(std::declval<T>().state())>> : std::true_type {};
template <class T>
inline constexpr bool has_member_state_v = has_member_state<T>::value;
template <class T, class = void>
struct has_non_member_state : std::false_type {};
template <class T>
struct has_non_member_state<T, std::void_t<decltype(state(std::declval<T>()))>> : std::true_type {};
template <class T>
inline constexpr bool has_non_member_state_v = has_non_member_state<T>::value;
struct state_fn {
template <
class T,
std::enable_if_t<
std::conjunction_v<
has_member_variable_state<T>, //
std::negation<has_member_state<T>>, //
std::negation<has_non_member_state<T>>>,
int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept {
return beluga::forward_like<T>(t.state);
}
template <
class T,
std::enable_if_t<
std::conjunction_v<
std::negation<has_member_variable_state<T>>, //
has_member_state<T>, //
std::negation<has_non_member_state<T>>>,
int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept(noexcept(std::forward<T>(t).state())) {
return std::forward<T>(t).state();
}
template <
class T,
std::enable_if_t<
std::conjunction_v<
std::negation<has_member_variable_state<T>>, //
std::negation<has_member_state<T>>, //
has_non_member_state<T>>,
int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept(noexcept(state(std::forward<T>(t)))) {
return state(std::forward<T>(t));
}
template <
class T,
std::enable_if_t<
std::conjunction_v<
std::negation<has_member_variable_state<T>>, //
std::negation<has_member_state<T>>, //
std::negation<has_non_member_state<T>>, //
is_tuple_like<T>>,
int> = 0,
std::enable_if_t<(std::tuple_size_v<std::decay_t<T>> > 1), int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept(noexcept(std::get<0>(std::forward<T>(t)))) {
return std::get<0>(std::forward<T>(t));
}
};
} // namespace state_detail
inline constexpr state_detail::state_fn state;
namespace weight_detail {
template <class T, class = void>
struct has_member_variable_weight : std::false_type {};
template <class T>
struct has_member_variable_weight<T, std::void_t<decltype(std::declval<T>().weight)>> : std::true_type {};
template <class T>
inline constexpr bool has_member_variable_weight_v = has_member_variable_weight<T>::value;
template <class T, class = void>
struct has_member_weight : std::false_type {};
template <class T>
struct has_member_weight<T, std::void_t<decltype(std::declval<T>().weight())>> : std::true_type {};
template <class T>
inline constexpr bool has_member_weight_v = has_member_weight<T>::value;
template <class T, class = void>
struct has_non_member_weight : std::false_type {};
template <class T>
struct has_non_member_weight<T, std::void_t<decltype(weight(std::declval<T>()))>> : std::true_type {};
template <class T>
inline constexpr bool has_non_member_weight_v = has_non_member_weight<T>::value;
struct weight_fn {
template <
class T,
std::enable_if_t<
std::conjunction_v<
has_member_variable_weight<T>, //
std::negation<has_member_weight<T>>, //
std::negation<has_non_member_weight<T>>>,
int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept {
return beluga::forward_like<T>(t.weight);
}
template <
class T,
std::enable_if_t<
std::conjunction_v<
std::negation<has_member_variable_weight<T>>, //
has_member_weight<T>, //
std::negation<has_non_member_weight<T>>>,
int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept(noexcept(std::forward<T>(t).weight())) {
return std::forward<T>(t).weight();
}
template <
class T,
std::enable_if_t<
std::conjunction_v<
std::negation<has_member_variable_weight<T>>, //
std::negation<has_member_weight<T>>, //
has_non_member_weight<T>>,
int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept(noexcept(weight(std::forward<T>(t)))) {
return weight(std::forward<T>(t));
}
template <
class T,
std::enable_if_t<
std::conjunction_v<
std::negation<has_member_variable_weight<T>>, //
std::negation<has_member_weight<T>>, //
std::negation<has_non_member_weight<T>>, //
is_tuple_like<T>, //
has_single_element<beluga::Weight, std::decay_t<T>>>,
int> = 0>
constexpr decltype(auto) operator()(T&& t) const noexcept(noexcept(element<beluga::Weight>(std::forward<T>(t)))) {
return element<beluga::Weight>(std::forward<T>(t));
}
};
} // namespace weight_detail
inline constexpr weight_detail::weight_fn weight;
} // namespace beluga
#endif