2014-10-12 6 views
6

그의 CppCon 2014 탈크 에서 Scott Meyers는 auto에 대한 특별한 규칙이 있고 왜 C++ 11/C++ 14 표준 (그의 질문은 at 36m05s이라고 시작합니다)에서 이니셜 라이저를 보강했는지에 대한 질문을 던집니다.C++ 11/C++ 14에서 자동 및 브레이스 이니셜 라이저를위한 특수 유형 공제 규칙이있는 이유는 무엇입니까?

braced-init-list와 결합 된 auto의 의미는 §7.1.6.4/6에 정의되어 있습니다.


나는 그것에 대해 생각하고 유스 케이스도 생각해 낼 수 없었다. 지금까지 본 것 중에 가장 가까운 것은 Bjarne Stroustrup이 사용했던 한 예입니다.

그는 Cpp 2014 talk "Make Simple Tasks Simple!"에서 auto을 사용하여 이니셜 라이저를 캡처합니다 (단, 일시적인 해결책으로 만 사용 가능). 여기

코드 (슬라이드 (30)의 일부 at 37m10s)입니다 :

// auto ss1 = collect({ 1, 2, 3, 4, 5, 6 }, odd); // error: Bummer! 
    auto lst = { 1, 2, 3, 4, 5, 6 }; 
    auto ss2 = collect(lst, odd); // {1,3,5} 

그러나 그것은 단지 해결 방법입니다 있습니다. 그는 그것이 필요하지 않아야한다고 언급했다. 대신 그는 함수에 인수를 직접 전달하는 것을 선호합니다. 따라서, auto과 이니셜 라이저 목록에 대한 좋은 동기가 될 수는 없습니다. 그가 제안으로 C++의


나의 이해는, 비얀의 예에서 초기화-목록을 허용하는 단점을 판단 할만큼 깊은하지 않습니다. 어쨌든,이 경우에는 auto의 필요성을 피할 수 있습니다.

그래서 auto이고 이니셜 라이저 목록은 더 잘 해결되었을 수있는 해결 방법 일뿐입니다? 아니면 §7.1.6.4/6의 추가 자동 공제 규칙이 유용한 좋은 예가 있습니까?

template<class T> 
void inc(T, int); // (1) 

template<class T> 
void inc(std::initializer_list<T>, long); // (2) 

inc({1, 2, 3}, 3); // Calls (2). (If deduction had succeeded 
        // for (1), (1) would have been called — a 
        // surprise.) 

그러나 auto에 대한 특별한 예외를 조각 :

+0

'auto x = {expr};을 만들려는'expr' (괄호 안의 쉼표 연산자 제외) 형식을 사용합니다. 그래도 전체 목록에 사용할 다른 유형을 모르겠습니다. – chris

+0

@christ 나는 N3922를 의미한다고 생각합니다. Scott Meyers도 그렇게 언급합니다. Visual Studio는 C++ 14의 일부가 아니더라도 이미 구현합니다. 다음은 링크입니다. http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3922.html –

+0

아, 그 중 하나입니다. 이 사용법 때문에 나는 일반적인 종류에 동의하지 않아도된다. 그래도 형편없는 형식을 선호하고 이니셜 라이저 목록을 추가 선없이 함수에 전달할 수 있습니다. – chris

답변

8

근거는 일반적으로 보강 초기화 목록에서 일반 형식 매개 변수의 공제를 금지하고 싶었 N2640에 있습니다

한편, T에 대해 initializer_list<X>을 추론 할 수 있습니다. 수 있도록했습니다 :

초기화 목록에 대한 EWG 토론의 시작부터 바람직한 행동으로 간주되었다
auto x = { 1, 1, 2, 3, 5 }; 
f(x); 
g(x); 

. 파라미터 유형 T에 대한 영리한 공제 규칙을 {} -리스트 (이 문서의 이전 스케치 및 초안에서 추구했던 옵션)과 일치시키지 않고, 이제 의 특수 사례로 처리하는 것이 더 좋습니다. "자동"변수 이니셜 라이저가 {} - 목록 인 경우 공제. 즉, 특정 " "자동 입력 형식 지정자 및 {} - 목록 이니셜 라이저로 선언 된 변수의 경우 "auto"는 함수 f(initializer_list<T>) 대신에 f(T)과 같이 추론됩니다.

2

스콧 마이어스는 블로그 게시물에서 주제 연설 : T.C.의 대답처럼, 그것은 또한 N2640을 의미 Why auto deduces std::initializer_list for a braced initializer

. 특별 공제 규칙이 작동하려면이 같은 코드를 할 수 있도록 추가되었습니다

블로그 게시물에서
auto x = { 1, 1, 2, 3, 5 }; 
f(x); 
g(x); 

는 스콧 제임스 Hopkin에서 다음 설명을 인용 :

짧은 이야기는 N2640는 제안이다 특별한 경우 auto는 brace initializers를 initializer_lists로 추론해야하며, 균일 초기화를 깨뜨리지 않아야합니다 (예 : int x{7};auto x{7};은 매우 다릅니다). N3922은 다른 특별한 경우를 도입함으로써 (물론!) 단일 매개 변수가있는 이니셜 라이저에 자체 규칙이 있음을 수정했습니다.

약간 더 자세히 : N2640은 템플릿 인수 공제를 단순하게 유지하려고 시도하지만 브레이스 된 이니셜 라이저를 두 개 이상의 함수에 자동으로 할당하여 전달할 수 있습니다. 이것은 N2672에서 문구로 바뀌 었습니다. N2532에있는 Stroustrup의 이전 디자인은 제한되지 않은 템플릿 매개 변수와 auto에 대해 initializer_lists를 공제하도록 허용합니다.이 매개 변수는보다 일관성이 있으며 균일 한 초기화도 손상시킵니다.

아무 이유없이 이것은 N3922이 자동 특수 케이스를 제거하지 않은 이유를 설명하지 않습니다. 그렇다고해서 코드의 의미를 조용히 변경하지 못했고 언어를 단순화했을 것입니다.