<질문>
기본 템플릿 인수가 클래스 템플릿에서만 허용되는 이유는 무엇입니까? 멤버 함수 템플릿에서 기본 유형을 정의 할 수없는 이유는 무엇입니까? 예를 들면 :
struct mycclass {
template
void mymember(T* vec) {
// ...
}
};
대신 C ++에서는 기본 템플릿 인수가 클래스 템플릿에서만 허용되도록 강제합니다.
<답변1>
기본 템플릿 인수를 제공하는 것이 좋습니다. 예를 들어 정렬 함수를 만들 수 있습니다.
template::value_type> >
void sort(Iterator beg, Iterator end, Comp c = Comp()) {
...
}
C ++ 0x는이를 C ++에 도입합니다. Bjarne Stroustrup의이 결함 보고서 : 함수 템플릿에 대한 기본 템플릿 인수 및 그가 말하는 내용을 참조하십시오.
함수 템플릿에 대한 기본 템플릿 인수의 금지는 독립 함수가 2 급 시민으로 취급되고 모든 템플릿 인수가 지정되지 않고 함수 인수에서 추론되도록 요구했던 시대의 오해의 흔적입니다. 이 제한은 불필요하게 독립 함수를 멤버 함수와 다르게 만들어 프로그래밍 스타일을 심각하게 제한하므로 STL 스타일 코드를 작성하기가 더 어려워집니다.
<답변2>
C ++ 템플릿을 인용하려면 : 전체 가이드 (207 페이지) :
템플릿이 원래 C ++ 언어에 추가되었을 때 명시 적 함수 템플릿 인수는 유효한 구성이 아닙니다. 함수 템플릿 인수는 항상 호출 표현식에서 추론 할 수 있어야했습니다. 결과적으로 기본값은 항상 추론 된 값으로 재정의되기 때문에 기본 함수 템플릿 인수를 허용해야하는 설득력있는 이유가없는 것 같습니다.
<답변3>
지금까지 함수 템플릿에 대한 기본 템플릿 매개 변수의 모든 제안 된 예제는 오버로드로 수행 할 수 있습니다.
알코올:
struct S {
template R get_me_R() { return R(); }
};
다음과 같을 수 있습니다.
struct S {
template R get_me_R() { return R(); }
int get_me_R() { return int(); }
};
내 자신의:
template int &increment(int &i) { i += N; return i; }
다음과 같을 수 있습니다.
template int &increment(int &i) { i += N; return i; }
int &increment(int &i) { return increment<1>(i); }
litb :
template >
void sort(Iterator beg, Iterator end, Comp c = Comp())
다음과 같을 수 있습니다.
template
void sort(Iterator beg, Iterator end, std::less c = std::less())
template
void sort(Iterator beg, Iterator end, Comp c = Comp())
Stroustrup :
template
void f(T t = 0, U u = 0);
다음과 같을 수 있습니다.
template void f(S s = 0, T t = 0);
template void f(S s = 0, double t = 0);
다음 코드로 증명했습니다.
#include
#include
#include
#include
template T prettify(T t) { return t; }
std::string prettify(char c) {
std::stringstream ss;
if (isprint((unsigned char)c)) {
ss << "'" << c << "'";
} else {
ss << (int)c;
}
return ss.str();
}
template void g(S s, T t){
std::cout << "f<" << typeid(S).name() << "," << typeid(T).name()
<< ">(" << s << "," << prettify(t) << ")\n";
}
template void f(S s = 0, T t = 0){
g(s,t);
}
template void f(S s = 0, double t = 0) {
g(s, t);
}
int main() {
f(1, 'c'); // f(1,'c')
f(1); // f(1,0)
// f(); // error: T cannot be deduced
f(); // f(0,0)
f(); // f(0,0)
}
인쇄 된 출력은 f에 대한 각 호출의 주석과 일치하며 주석 처리 된 호출은 예상대로 컴파일되지 않습니다.
그래서 나는 기본 템플릿 매개 변수가 "필요하지 않다"고 생각하지만 아마도 기본 함수 인수가 "필요하지 않다"는 것과 같은 의미 일 것입니다. Stroustrup의 결함 보고서에서 알 수 있듯이 추론되지 않은 매개 변수를 추가하는 것은 너무 늦어서 기본값을 유용하게 만들었다는 사실을 누구든지 깨닫거나 감사하기에는 너무 늦었습니다. 따라서 현재 상황은 결코 표준이 아닌 기능 템플릿 버전을 기반으로합니다.
<답변4>
Windows에서는 모든 버전의 Visual Studio에서이 오류 (C4519)를 경고로 변환하거나 다음과 같이 비활성화 할 수 있습니다.
#ifdef _MSC_VER
#pragma warning(1 : 4519) // convert error C4519 to warning
// #pragma warning(disable : 4519) // disable error C4519
#endif
여기에서 자세한 내용을 확인하세요.
<답변5>
내가 사용하는 것은 다음 트릭입니다.
다음과 같은 기능을 원한다고 가정 해 보겠습니다.
template > void doStuff(ARR_E array)
{
E one(1);
array.add( one );
}
당신은 허용되지 않을 것이지만 다음 방법으로 수행합니다.
template
struct MyArray_t {
void add(T i)
{
// ...
}
};
template >
class worker {
public:
/*static - as you wish */ ARR_E* parr_;
void doStuff(); /* do not make this one static also, MSVC complains */
};
template
void worker::doStuff()
{
E one(1);
parr_->add( one );
}
따라서 이렇게하면 다음과 같이 사용할 수 있습니다.
MyArray_t my_array;
worker w;
w.parr_ = &arr;
w.doStuff();
두 번째 매개 변수를 명시 적으로 설정할 필요가 없음을 알 수 있습니다. 누군가에게 유용 할 수도 있습니다.
'개발 > C++' 카테고리의 다른 글
보호 또는 개인 생성자 만있는 클래스에서 :: std :: make_shared를 어떻게 호출합니까? (0) | 2020.09.30 |
---|---|
흥미로운 반복 템플릿 패턴 (CRTP)은 무엇입니까? (0) | 2020.09.30 |
4x4 행렬 반전 (0) | 2020.09.26 |
"계속하려면 아무 키나 누르시겠습니까?"를 시뮬레이션하는 방법 (0) | 2020.09.26 |