2013-05-20 7 views

답변

12

이것은 처음에 기대할 수있는 것보다 훨씬 까다로운 사례 중 하나입니다.

D가 C++에 비해 중요하고 유용한 기능 중 하나는 모든 사용자 유형을 포함하여 모든 단일 유형에는 컴파일시 평가할 수있는 초기 비가시 값이 있다는 것입니다.

template isSomething(T) { 
    enum isSomething = is(typeof({ 
     //T t1;      // not good if T is nested struct, or has @disable this() 
     //T t2 = void; auto x = t2; // not good if T is non-mutable type 
     T t = T.init;    // avoid default construct check 
     ...use t... 
    })); 
} 
: 특정 작업이 지정된 형태에 할 수 있으면 (켄지하라의 조각을 인용) 확인 T.init 값을 사용할 수 있습니다

  1. 템플릿 제약 : T.init로 사용이 중요한 사용 사례를 가지고있다

  2. int i = void 구문을 명시 적으로 사용하지 않으면 변수가 항상 올바르게 초기화됩니다. 가능한 쓰레기가 없습니다.

이 점을 감안할 때, 어려운 질문이 생깁니다. 우리는 T()와 T.init (C++에서 기대하는 많은 프로그래머가 기대할 수있는)가 동일하거나 그 보증을 쉽게 파괴 할 수있는 기본 구성을 허용해야 함을 보장해야합니다. 내가 아는 한, 놀라운 것은 있음에도 불구하고 첫 번째 접근이 더 안전하다는 결정이 내려졌습니다.

그러나 토론은 제안 된 다양한 개선 사항으로 계속 나타납니다 (예 : CTFE 가능 기본 생성자 허용). 하나의 such thread이 최근에 나타났습니다.

8

이것은 D의 모든 유형에 기본값이 있어야한다는 사실에서 유래합니다. 배열의 모든 값을 할당 할 때 기본 값 초기화 멤버 변수 및 기본 값 초기화와 같은 유형을 포함하여 유형의 init 값이 사용되는 곳이 많습니다. 이러한 경우에 대해 init을 컴파일 할 때 알 필요가 있습니다. init을 사용하면 많은 이점을 얻을 수 있지만 기본 생성자를 사용하는 방식으로 진행됩니다.

실제 기본 생성자는 init이 사용되는 모든 장소에서 사용되어야하지만 (기본값이 아닐 수도 있음) init이 사용되는 여러 경우에 임의의 코드가 실행될 수 있습니다. 기껏해야 문제가된다. 최소한 CTFE 가능하고 아마도 pure이되도록해야합니다. 그리고 곧 그와 같은 제한을두기 시작하자마자, 여러분은 많은 멤버쉽 변수를 직접 얻지 않을 것이므로 (예 : init의 경우) 원하는 모든 멤버 변수를 직접 초기화 할 수 있습니다 뭔가 이상한 경우), 기본 생성자를 쓸모 없게 만들 것입니다.

init과 기본 생성자를 모두 가질 수는 있지만 그 중 하나가 다른 것보다 많이 사용되는 경우에 대한 질문이 나오고 기본 생성자가 더 이상 기본값이 아닙니다. 말할 것도없이, init 값이 사용 된시기와 기본 생성자가 사용 된시기는 개발자에게 매우 혼란 스러울 수 있습니다.

이제, 우리는가,이 경우, init을 필요한 상황에서 그 구조체를 사용하는 것은 불법 것 (문제의 자체적 인 원인) 구조체의 init 값을 @disable 수있는 능력을 가지고 할 . 그래서 런타임에 임의의 코드를 실행할 수있는 기본 생성자를 가질 수는 있지만 그 정확한 결과는 무엇인지 모르겠습니다. 그러나 사람들이 init을 필요로하는 기본 생성자를 갖고 싶기 때문에 @disabled 되었기 때문에 작동하지 않을 것이라는 확신이들 것입니다 (유형의 배열을 선언하는 것이 아마도 그 중 하나 일 것입니다).

D가 수행 한 작업을 init으로 수행하면 기본 생성자에 대한 전체 질문이 다른 언어보다 훨씬 복잡하고 문제가됩니다.

기본 구성과 비슷한 것을 얻는 정상적인 방법은 정적 인 opCall을 사용하는 것입니다. 예를 들어, -

struct S 
{ 
    static S opCall() 
    { 
     //Create S with the values that you want and return it. 
    } 
} 

그럼 당신은 사용할 때마다 S() 같은 뭔가

auto s = S(); 

은 다음 정적 opCall 호출, 당신은 런타임에 생성 된 값을 얻을됩니다. 그러나 S.init은 이전의 장소 (S s; 포함)에서 계속 사용되며 opCallS()이 명시 적으로 사용될 때만 사용됩니다. 그러나 만약 당신이 @disable this() (이는 init 속성을 사용할 수 없음)과 연결하면 앞에서 설명한 @disabled init이있는 기본 생성자가있는 곳과 비슷한 것을 얻을 수 있습니다.

결국 언어에 추가되는 기본 생성자로 끝날 수도 있고 끝나지 않을 수도 있지만 init 및 언어가 작동하는 방식으로 인해 추가하는 데 기술적 인 문제가 있습니다. 추가해야합니다. 따라서 기본 생성자가 언어에 추가되기 위해서는 누군가가 (Walter를 설득하는 것을 포함하여) 모든 문제를 적절하게 해결하는 정말로 매력적인 디자인을 만들어야합니다. 그런 일은 일어나지 않을 것이라고 기대하지만, 만나다.