2015-02-06 2 views
10

초기화리스트 표현은 C++ 용기 초기화 정말 편리 연산 식 :전달 이니셜 라이저 목록

std::vector<int>({1, 2, 3}) 

를 ... 그러나 그것은 보인다 함수에 {1,2,3} 것이다 바인드 같은 중괄호로 둘러싸인 초기화리스트 표현,

template <class T> 
void foo(T&& v) 
{ 
    std::vector<int>(std::forward<T>(v)); 
} 

int main() 
{ 
    foo({1, 2, 3}) 
} 
0,123,516 : 보편적 인 (전달) 참조에 결합하는 것 같지 않습니다 - 그는이 std::initializer_list<int> 소요

이 출력 :

test2.cpp:11:6: note: template<class U> void foo(U&&) 
test2.cpp:11:6: note: template argument deduction/substitution failed: 
test2.cpp:33:13: note: couldn't deduce template parameter ‘U’ 

(이 GCC 4.7.2와 결과였다.)

불행히도 이것은 우리가 초기화리스트 식을 전달할 수 있다는 것을 의미한다. 그렇게하는 것이 매우 편리 할 것이므로 왜 이것이 작동하지 않는지 묻고 싶습니다. 중괄호가 이니셜 라이저 목록 표현식을 전달 참조에 바인드 할 수없는 이유는 무엇입니까? 아니면이 허용되고, 아마도 내 컴파일러는 너무 오래 되었습니까?

+1

'initializer_list'를 전달하는 것은 쓸모가 없습니다. 이미 참조 의미를 가지고 있으며 그 요소는 const이며, 따라서 움직일 수 없습니다. – dyp

+0

이동 가능한지 여부는 중요하지 않습니다. 범용 전달 참조는 반드시 이동을 의미하지는 않으며 – Siler

+3

과 같이 매개 변수를 따라 전달하는 것을 의미합니다. 예,하지만 braced-init-list에는 유형이 없습니다. 따라서, "있는 그대로"전달할 수는 없습니다. – dyp

답변

10

함수의 매개 변수에 바인딩 할 수있는 것은 아닙니다. 컴파일러가 템플릿의 유형을 감지 할 수 없다는 것입니다. 이 경우 컴파일됩니다 :

#include <vector> 

template <class T> 
void foo(T&& v) 
{ 
    std::vector<int>(std::forward<T>(v)); 
} 

int main() 
{ 
    foo(std::initializer_list<int>{1, 2, 3}); 
} 
3

이 경우 이니셜 라이저 목록을 추론 할 수 없습니다. 이것은 실제로 [temp.deduct.call]에서 표준에 의해 명시 적으로 포함되는 각각의 기능 템플릿 파라미터 유형을 비교함으로써 수행된다

템플릿 인수 공제 과의 대응하는 인수의 유형 (P를 호출) 아래 전화 번호 (A)로 전화하십시오. P이 종속 유형 인 경우 [...]. 그렇지 않으면 이니셜 라이저 목록 인수로 인해 매개 변수가 추론되지 않은 컨텍스트 (14.8.2.5)로 간주됩니다. [예 :

template<class T> void f(std::initializer_list<T>); 
f({1,2,3}); // T deduced to int 
f({1,"asdf"}); // error: T deduced to both int and const char* 

template<class T> void g(T); 
g({1,2,3}); // error: no argument deduced for T 

여기 g의 예는 정확히 경우입니다 - T 종속 형식이 아닙니다, 그래서 이것은 비 추론 문맥으로 간주됩니다. 컴파일러는 코드를 거부하는 것이 옳습니다.

관련 문제