doo*_*pav 0 c++ compile-time variadic-templates stdtuple c++17
我想首先说明,当我说同构元组时,我的意思是每个元素的类型都是相同的,或者每个元素都有一个公共成员,该成员在所有元素中都是相同的类型。在这种情况下,公共成员也必须是static constexpr
。
这是描述我的问题的一段简化代码:
#include <cstddef>
#include <tuple>
#include <type_traits>
#include <utility>
template <std::size_t N>
struct Int : std::integral_constant<std::size_t, N>
{
Int() = default;
Int(const Int&) = delete;
Int(Int&&) = delete;
Int& operator=(const Int&) = delete;
Int& operator=(Int&&) = delete;
};
template <std::size_t... Ns>
struct Stuff
{
using type = std::tuple<Int<Ns>...>;
using arr_type = std::array<std::size_t, std::tuple_size_v<type>>;
static constexpr arr_type arr = {Ns...};
};
Run Code Online (Sandbox Code Playgroud)
我相当确定它是正确的,唯一的问题是最后一行,但希望你明白要点。
现在,数组是使用Ns...
. 我希望能够从而type
不是构造数组(原因是type
已经从元组中删除了重复类型(基于.value
),并且还在.value
此代码的实际版本中对类型进行了排序(基于))。如果相反,在编译时从数组中排序和删除重复值更容易,那么这也将被接受作为答案。
所以理想情况下,我会编写某种模板化结构来创建数组(因为在结构中会有一个static constexpr arr_type value =
成员),并且在Stuff
结构中,我会arr
像这样初始化成员:
static constexpr arr_type arr = detail::make_array_v<type>;
Run Code Online (Sandbox Code Playgroud)
Int
如果绝对必要,我愿意取消对结构的复制构造/分配的限制。我不知道如何为此编写一个辅助函数/结构,任何帮助表示赞赏。答案可以使用任何版本的 c++,直到并包括 c++20。
我认为这以某种通用的方式解决了您的问题:
namespace detail {
template <class Tuple>
struct make_array;
template <class V, template <V N> class C, V... Ns>
struct make_array<std::tuple<C<Ns>... >> {
static constexpr std::array value{Ns... };
};
template <class Tuple>
constexpr auto make_array_v = make_array<Tuple>::value;
}
Run Code Online (Sandbox Code Playgroud)
它基本上是一个模板std::tuple
专业化std::tuple
与值列表的模板参数的。
以下是可能的用法(假设Char
类似于您的Int
bur for char
):
constexpr auto arr1 = detail::make_array_v<std::tuple<Int<42>, Int<38>, Int<57>>>;
static_assert(arr1 == std::array<std::size_t, 3>{42, 38, 57});
constexpr auto arr2 = detail::make_array_v<std::tuple<Char<'A'>, Char<'Z'>,
Char<'w'>, Char<'U'>>>;
static_assert(arr2 == std::array{'A', 'Z', 'w', 'U'});
Run Code Online (Sandbox Code Playgroud)
该实现对 C++17 有效,我认为转换为 C++14 很容易(你只需要为 指定模板参数value
)。上面的测试需要 C++20constexpr
作为std::array
.
完整的 Godbolt.org 代码与您的示例:https ://godbolt.org/z/jkiA9R