이 질문이 제기 된 이후 두 가지 새로운 표준과 곧 새로운 표준이있는 2016 년의 계몽 된 시대에 알아야 할 중요한 것은 C ++ 17 표준을 지원 하는 컴파일러가 코드를 그대로 컴파일 한다는 것 입니다. .
C ++ 17의 클래스 템플릿에 대한 템플릿 인수 추론
여기 (수락 된 답변에 대한 Olzhas Zhumabek의 편집에 의함)는 표준에 대한 관련 변경 사항을 자세히 설명하는 문서입니다.
다른 답변의 문제 해결
현재 최고 등급 답변
이 답변은 "복사 생성자 및 operator=
"가 올바른 템플릿 전문화를 알지 못함을 나타냅니다.
표준 복사 생성자 가 알려진 템플릿 유형에 operator=
대해서만 존재 하기 때문에 이것은 말도 안됩니다 .
template <typename T>
class MyClass {
MyClass(const MyClass&) =default;
... etc...
};
// usage example modified from the answer
MyClass m(string("blah blah blah"));
MyClass *pm; // WHAT IS THIS?
*pm = m;
내가 코멘트에서 언급 한 바와 같이 여기,이없는 이유 에 대한 MyClass *pm
또는 추론의 새로운 형태없이 법적 선언 할 수는 : MyClass
유형없는 이의 포인터를 선언하는 이해가되지 않도록, (그것은 템플릿입니다) 유형 MyClass
. 다음은 예를 수정할 수있는 한 가지 방법입니다.
MyClass m(string("blah blah blah"));
decltype(m) *pm; // uses type inference!
*pm = m;
여기서, pm
이다 이미 추론이 사소한 올바른 유형의, 그리고 있도록. 또한 복사 생성자를 호출 할 때 실수로 유형을 혼합하는 것은 불가능합니다 .
MyClass m(string("blah blah blah"));
auto pm = &(MyClass(m));
여기 pm
에의 복사본에 대한 포인터가 있습니다 m
. 여기서, MyClass
복사 - 구성되는 m
- 어떤 유형이다 MyClass<string>
(그리고 되지 존재하지 않는 타입 MyClass
). 따라서, 지점 pm
의 유형을 유추됩니다, 거기 이다 의 템플릿 형 있음을 알 수있는 충분한 정보 m
, 따라서의 템플릿 유형 pm
이다가 string
.
또한 다음은 항상 컴파일 오류를 발생시킵니다 .
MyClass s(string("blah blah blah"));
MyClass i(3);
i = s;
복사 생성자의 선언이 있기 때문입니다 하지 템플릿 :
MyClass(const MyClass&);
여기서 copy-constructor 인자의 template-type 은 전체 클래스 의 template-type 과 일치 합니다. 즉이 경우, MyClass<string>
인스턴스화, MyClass<string>::MyClass(const MyClass<string>&);
그것을 인스턴스화되고, 때 MyClass<int>
인스턴스화, MyClass<int>::MyClass(const MyClass<int>&);
인스턴스화됩니다. 명시 적으로 지정되거나 템플릿 화 된 생성자가 선언되지 않는 한 컴파일러가을 인스턴스화 할 이유가 없으며 MyClass<int>::MyClass(const MyClass<string>&);
이는 분명히 부적절합니다.
Cătălin Pitiș의 답변
Pitiș는 및를 추론하는 예제를 제공하고 다음 Variable<int>
과 Variable<double>
같이 말합니다.
두 가지 유형 (Variable 및 Variable)의 코드에 동일한 유형 이름 (Variable)이 있습니다. 내 주관적인 관점에서 볼 때 코드의 가독성에 거의 영향을 미칩니다.
이전 예제에서 언급했듯이 , 새로운 기능이 구문 상 하나처럼 보이더라도 Variable
그 자체는 유형 이름 이 아닙니다 .
그런 다음 Pitiș는 적절한 추론을 허용하는 생성자가 제공되지 않으면 어떻게 될 것인지 묻습니다. 대답은 추론이 생성자 호출 에 의해 트리거되기 때문에 추론이 허용되지 않는다는 것입니다 . 생성자 호출이 없으면 추론 이 없습니다 .
이것은 foo
여기서 추론 된 버전을 묻는 것과 유사합니다 .
template <typename T> foo();
foo();
대답은 명시된 이유 때문에이 코드가 불법이라는 것입니다.
MSalter의 답변
이것이 제가 말할 수있는 한, 제안 된 기능에 대한 합법적 인 우려를 제기하는 유일한 대답입니다.
예는 다음과 같습니다.
Variable var(num); // If equivalent to Variable<int> var(num),
Variable var2(var); // Variable<int> or Variable<Variable<int>> ?
핵심 질문은 컴파일러가 여기서 유형 유추 생성자를 선택 합니까 아니면 복사 생성자를 선택합니까?
코드를 시도해 보면 복사 생성자가 선택되었음을 알 수 있습니다. 예제를 확장하려면 :
Variable var(num); // infering ctor
Variable var2(var); // copy ctor
Variable var3(move(var)); // move ctor
// Variable var4(Variable(num)); // compiler error
나는 제안과 표준의 새 버전이 이것을 어떻게 명시하고 있는지 잘 모르겠습니다. 그것은 내가 아직 이해하지 못하는 새로운 표준 인 "추론 가이드"에 의해 결정된 것 같습니다.
나는 또한 var4
공제가 왜 불법 인지 잘 모르겠습니다 . g ++의 컴파일러 오류는 명령문이 함수 선언으로 구문 분석되고 있음을 나타내는 것 같습니다.