Edm*_*und 4 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.
}
Run Code Online (Sandbox Code Playgroud)
产量如下:
1,2,3
-326483696,32767,0
Run Code Online (Sandbox Code Playgroud)
这有什么不对?
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);
}
Run Code Online (Sandbox Code Playgroud)