Programing

std :: initializer_list가 기본 제공 언어가 아닌 이유는 무엇입니까?

crosscheck 2020. 9. 2. 14:12
반응형

std :: initializer_list가 기본 제공 언어가 아닌 이유는 무엇입니까?


std::initializer_list핵심 언어가 기본으로 제공 되지 않는 이유는 무엇 입니까?

C ++ 11의 매우 중요한 기능이지만 자체 예약 된 키워드 (또는 유사)가없는 것 같습니다.

대신, initializer_list그건 단지 특별한 암시가 표준 라이브러리에서 템플릿 클래스 매핑 새로운에서 보강-초기화리스트 {...} 컴파일러에 의해 처리하는 것 구문을.

처음에이 솔루션은 상당히 엉망 입니다.

이것이 C ++ 언어에 대한 새로운 추가가 이제 구현되는 방식 입니까? 핵심 언어가 아닌 일부 템플릿 클래스의 암시 적 역할의해 구현 됩니까?


다음 예를 고려하십시오.

   widget<int> w = {1,2,3}; //this is how we want to use a class

왜 새로운 클래스가 선택 되었습니까?

   widget( std::initializer_list<T> init )

다음 아이디어 와 유사한 것을 사용하는 대신 :

   widget( T[] init, int length )  // (1)
   widget( T... init )             // (2)
   widget( std::vector<T> init )   // (3)
  1. const여기저기서 추가 할 수 있습니다.
  2. 언어에 이미 세 개의 점이 존재합니다 (var-args, 이제 가변 템플릿), 구문을 재사용하지 않는 이유 (그리고 내장 된 것처럼 느끼게 함 )
  3. 기존 컨테이너 만 추가 const하고&

그들 모두는 이미 언어의 일부입니다. 나는 첫 번째 아이디어를 세 개만 썼고 다른 많은 접근 방식 이 있다고 확신합니다 .


std네임 스페이스에 정의 된 유형을 반환하는 "핵심"언어 기능의 예가 이미있었습니다 . typeid반환 std::type_info하고 (아마도 점을 늘리면)를 sizeof반환합니다 std::size_t.

전자의 경우 소위 "핵심 언어"기능을 사용하려면 이미 표준 헤더를 포함해야합니다.

이제 이니셜 라이저 목록의 경우 객체를 생성하는 데 키워드가 필요하지 않으며 구문은 상황에 맞는 중괄호입니다. 그 외에는 type_info. 개인적으로 나는 키워드의 부재가 그것을 "더 해키"하게 만든다고 생각하지 않습니다. 약간 더 놀랍지 만, 목표는 이미 집계에 허용 된 것과 동일한 중괄호 이니셜 라이저 구문을 허용하는 것이 었습니다.

그렇습니다. 앞으로이 디자인 원칙을 더 많이 기대할 수 있습니다.

  • 새로운 키워드없이 새로운 기능을 도입 할 수있는 경우가 더 많이 발생하면위원회에서이를 채택합니다.
  • 새로운 기능에 복잡한 유형이 필요한 경우 해당 유형은 std내장이 아닌에 배치됩니다 .

그 후:

  • 새 기능에 복잡한 유형이 필요하고 새 키워드없이 도입 할 수있는 경우 여기에있는 것을 얻을 수 있습니다. 이는 새 키워드가없는 "핵심 언어"구문이며에서 라이브러리 유형을 사용합니다 std.

내 생각에는 C ++에서 "핵심 언어"와 표준 라이브러리 사이에 절대적인 구분이 없다고 생각합니다. 그것들은 표준의 다른 장이지만 각각은 다른 장을 참조하며 항상 그렇습니다.

C ++ 11에는 람다 가 컴파일러에 의해 생성 된 익명 형식 을 가진 개체를 도입하는 또 다른 접근 방식이 있습니다 . 이름이 없기 때문에 네임 스페이스에 전혀없고 std. 하지만 이니셜 라이저 목록에는 적합한 접근 방식이 아닙니다. 하나를 허용하는 생성자를 작성할 때 유형 이름을 사용하기 때문입니다.


C ++ 표준위원회는 새 키워드를 추가하지 않는 것을 선호하는 것 같습니다. 이는 기존 코드를 손상시킬 위험을 증가시키기 때문일 것입니다 (레거시 코드는 해당 키워드를 변수, 클래스 또는 다른 이름으로 사용할 수 있음).

또한 std::initializer_list템플릿 컨테이너로 정의하는 것은 매우 우아한 선택 인 것 같습니다. 키워드라면 기본 유형에 어떻게 액세스할까요? 어떻게 반복 하시겠습니까? 새로운 연산자도 많이 필요하며, 표준 컨테이너로 할 수있는 것과 동일한 작업을 수행하기 위해 더 많은 이름과 키워드를 기억해야합니다.

std::initializer_list다른 컨테이너와 같이 취급하면 이러한 것들과 함께 작동하는 일반 코드를 작성할 수 있습니다.

최신 정보:

그렇다면 기존의 조합을 사용하는 대신 새로운 유형을 도입하는 이유는 무엇입니까? (댓글에서)

우선 다른 모든 컨테이너에는 요소를 추가, 제거 및 대체하는 메서드가 있으며 이는 컴파일러 생성 컬렉션에는 바람직하지 않습니다. 유일한 예외는 std::array<>고정 된 크기의 C 스타일 배열을 래핑하므로 유일하게 합리적인 후보로 남을 것입니다.

그러나 니콜 올가미가 올바르게 코멘트 지적 간의 또 다른 중요한 차이점 std::initializer_list및 (을 포함한 모든 다른 표준 컨테이너 std::array<>) 후자 것들이있다이다 값 의미를 동시에 std::initializer_list갖는 참조 시맨틱 . 복사 std::initializer_list예를 들어, 여기에 포함 된 요소의 사본을 발생하지 않습니다.

또한 (다시 한 번 Nicol Bolas의 호의) 중괄호 초기화 목록에 대한 특수 컨테이너를 사용하면 사용자가 초기화를 수행하는 방식에 과부하가 걸릴 수 있습니다.


이것은 새로운 것이 아닙니다. 예를 들어, for (i : some_container)에 의존하는 특정 방법 또는 독립형 기능의 존재some_container클래스입니다. C #은 .NET 라이브러리에 더 많이 의존합니다. 사실, 이것은 언어 사양을 복잡하게하지 않고도 클래스를 일부 언어 구조와 호환되도록 만들 수 있기 때문에 이것은 매우 우아한 솔루션이라고 생각합니다.


이것은 실제로 새로운 것이 아니며 많은 사람들이 지적한 바 있습니다.이 관행은 C ++에 있었고 C #에도 있습니다.

Andrei Alexandrescu는 이것에 대해 좋은 점을 언급했습니다. 가상의 "핵심"네임 스페이스의 일부로 생각할 수 있습니다. 그러면 더 이해가 될 것입니다.

: 그래서, 실제로 같은 뭔가 core::initializer_list, core::size_t, core::begin(), core::end()과에 이렇게. std네임 스페이스 내부에 핵심 언어 구조 가있는 것은 불행한 우연입니다 .


표준 라이브러리에서 완벽하게 작동 할뿐만 아니라 표준 라이브러리에 포함되었다고해서 컴파일러가 영리한 트릭을 수행 할 수 없다는 의미는 아닙니다.

모든 경우에 할 수있는 것은 아니지만,이 유형은 잘 알려져 있거나 간단한 유형입니다.를 무시 initializer_list하고 초기화 된 값이 무엇인지에 대한 메모리 이미지를 갖게됩니다.

int i {5};에 해당 될 수 있습니다 int i(5);또는 int i=5;심지어 intwrapper iw {5};어디 intwrapper사소한 생성자가 복용하는 int 이상의 클래스 래퍼 간단한이다initializer_list


It's not part of the core language because it can be implemented entirely in the library, just line operator new and operator delete. What advantage would there be in making compilers more complicated to build it in?

참고URL : https://stackoverflow.com/questions/15198807/why-isnt-stdinitializer-list-a-language-built-in

반응형