gpt4 book ai didi

c++ - 在可变参数模板类中初始化数组

转载 作者:行者123 更新时间:2023-11-30 04:44:51 24 4
gpt4 key购买 nike

我无法理解可变参数模板。我想做很简单的事情

Tuple t{1,2,3};

应该创建包含数组 {1,2,3} ( t.data = {1,2,3} ) 的大小为 3 的元组

这意味着它应该做两件事:

  • 创建 Tuple<T,3>尺寸 3 ( Tuple<>::data[3] )
  • 填写Tuple<>::data用数字形式 std::initializer_list

这不起作用:

template<typename T, T...args>
struct Tuple{
T data[sizeof...(args)];
Tuple(const T& args...):data{args...}{};
};

我尝试了各种变体,例如:

template<typename T, T...args>
//template<typename T, Args...args>
struct Tuple{
T data[sizeof...(args)];
//T data{args...};

//template <typename ...Args>
//Tuple(T... args):data{args...}{};
Tuple(const T& args...):data{args...}{};
//Tuple(T* ...args):data{args...}{};
};

也许我不明白 T...argstypename ...Argsargs...

我试图用这个简单的例子来理解可变参数模板并避免使用 std::initializer_list

最佳答案

I cannot make my head around variadic tempates. I want to do very simple thing

Tuple t{1,2,3};

should crate tuple of size 3 containing array {1,2,3} ( t.data = {1,2,3})

不确定,但如果我理解正确的话,您正在尝试重新创建 std::array .

你想要的在 C++17 之前是不可能的,因为你的 Tuple它是一个模板类,因此在 C++17 之前,您需要明确模板参数。

从 C++17 开始,您可以使用演绎指南。

你想要的(再一次:如果我理解正确的话)几乎是 std::array deduction guide

template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;

在你的情况下成为

#include <type_traits>

template <typename T, std::size_t N>
struct Tuple
{
T data[N];
};

template <typename T, typename ... U>
Tuple(T, U...) -> Tuple<T, 1 + sizeof...(U)>;

int main ()
{
Tuple t{1, 2, 3};

static_assert( std::is_same_v<decltype(t), Tuple<int, 3u>> );
}

请注意,构造函数并不是严格必需的,因为参数用于初始化成员(C 样式数组)。

本推演指南

template <typename T, typename ... U>
Tuple(T, U...) -> Tuple<T, 1 + sizeof...(U)>;

推断 Tuple::data 的类型来自第一个参数的数组和另一个参数仅用于推断数组的大小;如果参数的类型不同,这可能是个问题;举例说明

Tuple t1{1l, 2, 3};  // become Tuple<long, 3u>
Tuple t2{2, 2l, 3}; // become Tuple<int, 3u>

还要考虑到,对于 std::array

The program is ill-formed if (std::is_same_v<T, U> && ...) is not true

要解决这个问题并有更灵活的东西,你可以使用std::common_type_t ,正如其他答案所建议的那样,因此推导指南变为

template <typename ... Ts>
Tuple(Ts...) -> Tuple<std::common_type_t<Ts...>, sizeof...(Ts)>;

两种情况都变成了Tuple<long, 3u>

Tuple t1{1l, 2, 3};  // become again Tuple<long, 3u>
Tuple t2{2, 2l, 3}; // now become Tuple<long, 3u>

Perhaps I don't get difference between T...args and typename ...Args and args...

寻找一本好的 C++ 书籍,但要使其简单

(1) typename ... Args声明一个类型的模板可变序列,用于类/结构,用于using声明,演绎指南,函数。

所以

 template <typename ... Args>
struct foo
{ };

定义一个接收零个或多个模板类型参数的模板结构,您可以如下声明一个变量

 foo<short, int, long, long long> f;

(2) T ... args声明一个不是类型而是类型元素的可变参数模板列表 T

什么是 T ?另一个模板参数。

因此,举例来说,您的一个 Tuple您问题中的版本

模板 结构元组 {/* ... */};

一个变量应该声明如下

Tuple<int, 1, 2, 3>  t{1, 2, 3}

在你的情况下这是非常多余的。

(3) args... (名称后带有省略号)是使用可变列表(类型或值)

举例

template <typename ... Args>
void foo (Args ... args)
{ bar(args...); }

声明并定义可变参数模板 foo()带有模板可变类型列表的函数

 template <typename ... Args> // <--- declare a variadic list of types Args

并且每种类型都对应一个值,因此您还声明了一个可变参数列表 args值(value)

 void foo (Args ... args) // <--- declare a variadic list of args values of types Args

并且声明扩展值包 args并将它们传递给另一个函数

 bar(args...);  // <--- expand the args pack and pass the value to bar.

关于c++ - 在可变参数模板类中初始化数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57540299/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com