* Copyright (c) 2025 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
* \file tuple.h
* \brief
*/
#ifndef TILEOP_UTILS_TUPLE_H
#define TILEOP_UTILS_TUPLE_H
#include "type_traits.h"
namespace Std {
constexpr uint32_t TILEOP_STD_TUPLE_STACK_DEEP = 64;
template <size_t N = 0, typename... Tps>
[host, aicore] inline void tuple_static_assert()
{
static_assert(N < TILEOP_STD_TUPLE_STACK_DEEP, "Index overflow, the index must be smaller than 64!");
static_assert(
sizeof...(Tps) <= TILEOP_STD_TUPLE_STACK_DEEP, "The number of template elements must be smaller than 64!");
}
template <typename... Tps>
class tuple;
template <>
class tuple<> {};
template <typename Tp, typename... Tps>
struct tuple_constraints {
using removeType = typename remove_reference<Tp>::type;
static constexpr bool variadic_copy_constructible = !is_same_v<Tp, removeType&&>;
};
template <typename Tp, typename... Tps>
class tuple<Tp, Tps...> : public tuple<Tps...> {
public:
[ host, aicore ] inline tuple() : tuple<Tps...>(), value_() { tuple_static_assert<0, Tp, Tps...>(); }
template <
typename Constraints = tuple_constraints<Tp, Tps...>,
enable_if_t<Constraints::variadic_copy_constructible, int> = 0>
[host, aicore] inline tuple(const Tp& val, const Tps&... params) : tuple<Tps...>(params...), value_(val)
{
tuple_static_assert<0, Tp, Tps...>();
}
[ host, aicore ] inline Tp& GetValue() noexcept { return value_; }
[ host, aicore ] inline const Tp& GetValue() const noexcept { return value_; }
template <typename Head, typename... Args>
[host, aicore] inline tuple<Tp, Tps...>& operator=(const tuple<Head, Args...>& t)
{
static_assert(sizeof...(Tps) == sizeof...(Args), "Both tuples must have the same number of elements.");
this->value_ = t.value_;
tuple<Tps...>(*this) = tuple<Args...>(t);
return *this;
}
private:
template <typename...>
friend class tuple;
Tp value_;
};
template <typename... Tps>
struct tuple_size;
template <typename... Tps>
struct tuple_size<tuple<Tps...>> : integral_constant<size_t, sizeof...(Tps)> {};
template <typename T>
struct tuple_size<const T> : public integral_constant<size_t, tuple_size<T>::value> {};
template <typename T>
struct tuple_size<const T&> : public integral_constant<size_t, tuple_size<T>::value> {};
template <typename T>
struct tuple_size<volatile T> : public integral_constant<size_t, tuple_size<T>::value> {};
template <typename T>
struct tuple_size<const volatile T> : public integral_constant<size_t, tuple_size<T>::value> {};
template <typename T>
constexpr size_t tuple_size_v = tuple_size<T>::value;
template <size_t N, typename... Tps>
struct tuple_element;
template <size_t N>
struct tuple_element<N, tuple<>> {
static_assert(N < 0, "The index(N) is greater than the number of elements!");
};
template <size_t N, typename Tp, typename... Tps>
struct tuple_element<N, tuple<Tp, Tps...>> : public tuple_element<N - 1, tuple<Tps...>> {};
template <typename Tp, typename... Tps>
struct tuple_element<0, tuple<Tp, Tps...>> {
using type = Tp;
using tuple_t = tuple<Tp, Tps...>;
};
template <size_t N, typename T>
struct tuple_element<N, const T> {
using type = const typename remove_const<typename tuple_element<N, T>::type>::type;
};
template <size_t N, typename T>
struct tuple_element<N, volatile T> {
using type = volatile typename remove_volatile<typename tuple_element<N, T>::type>::type;
};
template <size_t N, typename T>
struct tuple_element<N, const volatile T> {
using type = const volatile typename remove_cv<typename tuple_element<N, T>::type>::type;
};
template <typename T>
struct IsTupleImpl {
private:
template <typename Ts>
[host, aicore] inline static auto HasTupleSize(int32_t) -> bool_constant<(tuple_size<Ts>::value >= 0)>;
template <typename Ts>
[host, aicore] inline static auto HasTupleSize(uint32_t) -> false_type;
public:
static constexpr bool value = decltype(HasTupleSize<T>(static_cast<int32_t>(0)))::value;
};
template <typename T>
struct is_tuple : bool_constant<IsTupleImpl<T>::value> {};
template <typename T>
constexpr bool is_tuple_v = is_tuple<T>::value;
template <typename Tp>
[host, aicore] inline constexpr Tp&& forward(remove_reference_t<Tp>& t) noexcept
{
return static_cast<Tp&&>(t);
}
template <typename Tp>
[host, aicore] inline constexpr Tp&& forward(remove_reference_t<Tp>&& t) noexcept
{
static_assert(!is_lvalue_reference<Tp>::value, "Cannot forward an rvalue as an lvalue");
return static_cast<Tp&&>(t);
}
template <typename T>
struct unwrap_refwrapper {
using type = T;
};
template <typename T>
struct unwrap_refwrapper<std::reference_wrapper<T>> {
using type = T&;
};
template <typename T>
using unwrap_decay_t = typename unwrap_refwrapper<decay_t<T>>::type;
template <typename... Tps>
[host, aicore] inline constexpr tuple<unwrap_decay_t<Tps>...> make_tuple(Tps&&... args)
{
tuple_static_assert<0, Tps...>();
return tuple<unwrap_decay_t<Tps>...>(forward<Tps>(args)...);
}
template <typename... Tps>
[host, aicore] inline constexpr tuple<Tps&...> tie(Tps&... args) noexcept
{
tuple_static_assert<0, Tps...>();
return tuple<Tps&...>(args...);
}
template <typename... Tps>
[host, aicore] inline constexpr tuple<Tps&&...> forward_as_tuple(Tps&&... args) noexcept
{
tuple_static_assert<0, Tps...>();
return tuple<Tps&&...>(forward<Tps>(args)...);
}
template <size_t N, typename... Tps>
[host, aicore] inline typename tuple_element<N, tuple<Tps...>>::type& get(tuple<Tps...>& t) noexcept
{
tuple_static_assert<N, Tps...>();
using type = typename tuple_element<N, tuple<Tps...>>::type;
using tuple_t = typename tuple_element<N, tuple<Tps...>>::tuple_t;
return static_cast<type&>(static_cast<tuple_t&>(t).GetValue());
}
template <size_t N, typename... Tps>
[host, aicore] inline const typename tuple_element<N, tuple<Tps...>>::type& get(const tuple<Tps...>& t) noexcept
{
tuple_static_assert<N, Tps...>();
using type = const typename tuple_element<N, tuple<Tps...>>::type;
using tuple_t = const typename tuple_element<N, tuple<Tps...>>::tuple_t;
return static_cast<type&>(static_cast<tuple_t&>(t).GetValue());
}
template <size_t N, typename... Tps>
[host, aicore] inline typename tuple_element<N, tuple<Tps...>>::type&& get(tuple<Tps...>&& t) noexcept
{
using type = typename tuple_element<N, tuple<Tps...>>::type;
return static_cast<type&&>(get<N, Tps...>(static_cast<tuple<Tps...>&>(t)));
}
template <size_t N, typename... Tps>
[host, aicore] inline const typename tuple_element<N, tuple<Tps...>>::type&& get(const tuple<Tps...>&& t) noexcept
{
using type = const typename tuple_element<N, tuple<Tps...>>::type;
return static_cast<type&&>(get<N, Tps...>(static_cast<const tuple<Tps...>&>(t)));
}
}
#endif