2013-09-28 2 views
4

Я пытаюсь использовать шаблон функции 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

Initializer не предназначены быть проведены и использоваться в дальнейшем. – chris

+0

Копирование 'initializer_list' (например, при возврате из функции) не копирует базовые элементы. – jrok

ответ

7

std::initializer_list<T> должен использоваться только как временный объект или параметр функции, поскольку он относится к временному массиву.

8.5.4/5-6:

Объект типа std::initializer_list<E> строится из списка инициализатора, как если реализация выделяется временный массив N элементов типа const E, где N - количество элементов в списке инициализаторов. ...

Массив имеет то же время жизни, что и любой другой временный объект (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); 
} 
Смежные вопросы