在模板函数中使用initializer_list

Using initializer_list in template function

本文关键字:initializer list 函数      更新时间:2023-10-16

我正在尝试使用函数模板foo将参数转换为initializer_list。但是,它转换initializer_list具有与输入参数不同的奇怪值。

#include <iostream>
#include <iterator>
#include <string>
#include <vector>
using namespace std;
template<class T>
void func(std::initializer_list<T> a_args)
{
    if (a_args.begin() != a_args.end())
    {
        auto last = prev(a_args.end());
        copy(a_args.begin(), last, ostream_iterator<int>(cout, ","));
        cout << *last;
    }
    cout << endl;
}
template<class T, class ...Args>
struct first_of
{
    typedef T type;
};
template<class ...Args>
initializer_list<typename first_of<Args...>::type> foo(Args&&... args)
{
    return { forward<Args>(args)... };
}
int main()
{
    func({1,2,3});
    auto x = foo(1,2,3);
    func(x); //this should be the same as func({1,2,3}) but not.
}

实时代码

输出如下:

1,2,3
-326483696,32767,0

这是怎么回事?

std::initializer_list<T>只能用作临时对象或函数参数,因为它引用了一个临时数组。

8.5.4/5-6:

类型为 std::initializer_list<E> 的对象是从初始值设定项

列表构造的,就好像实现分配了一个 N 个类型为 const E 的元素的临时数组,其中 N 是初始值设定项列表中的元素数。

该数组与任何其他临时对象 (12.2( 具有相同的生存期,只是从数组初始化 initializer_list 对象会延长数组的生存期,就像将引用绑定到临时对象一样。

18.9/2:

类型 initializer_list<E> 的对象提供对类型为 const E 的对象数组的访问。 [注意:一对指针或一个指针加上一个长度将是initializer_list的明显表示。 initializer_list 用于实现 8.5.4 中指定的初始值设定项列表。 复制初始值设定项列表不会复制基础元素。

因此,返回一个initializer_list对象与

struct int_ref {
    int& ref;
    explicit constexpr int_ref(int& r) : ref(r) {}
};
int_ref func() {
    int n = 5;
    return int_ref(n);
}