2013-09-28 42 views
4

我正在嘗試使用函數模板foo將參數轉換爲initializer_list。但是,它轉換的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

初始化列表並不意味着舉行,以後使用。 – chris

+0

複製'initializer_list'(例如從函數返回時)不會複製基礎元素。 – jrok

回答

7

std::initializer_list<T>應僅用作臨時對象或函數參數,因爲它引用臨時數組。

8.5.4/5-6:

std::initializer_list<E>類型的對象是從初始化列表如同實施分配的const E類型的Ñ元素,其中Ñ臨時數組構造是初始化程序列表中元素的數量。 ...

除了初始化數組中的initializer_list對象延長數組的壽命,就像將引用綁定到臨時對象一樣,該數組的壽命與其他臨時對象(12.2)的壽命相同。

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); 
}