在模板函数中使用initializer_list

时间:2013-09-28 12:30:06

标签: c++ templates c++11

我正在尝试使用函数模板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.
}

LIVE CODE

输出如下:

1,2,3
-326483696,32767,0

这里有什么问题?

1 个答案:

答案 0 :(得分:7)

std::initializer_list<T>应仅用作临时对象或函数参数,因为它引用临时数组。

8.5.4 / 5-6:

  

类型为std::initializer_list<E>的对象是从初始化列表构造的,就好像该实现分配了一个类型为const E N 元素的临时数组,其中 N < / em>是初始化列表中的元素数。 ...

     

该数组与任何其他临时对象(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);
}