[C++] 함수 템플릿의 기본 템플릿 인수


Answers

기본 템플릿 인수를 제공하는 것이 좋습니다. 예를 들어 정렬 함수를 만들 수 있습니다.

template<typename Iterator, 
         typename Comp = std::less<
            typename std::iterator_traits<Iterator>::value_type> >
void sort(Iterator beg, Iterator end, Comp c = Comp()) {
  ...
}

C ++ 0x는 그것들을 C ++에 소개합니다. Bjarne Stroustrup의 결함 보고서 참조 : 기능 템플릿의 기본 템플릿 인수 및 그가 말한 내용

함수 템플릿에 대한 기본 템플릿 인수의 금지는 독립 함수가 제 2 클래스 시민으로 취급되고 모든 템플릿 인수가 지정된 인수가 아닌 함수 인수에서 추론되어야하는 시간의 오해 된 남은 부분입니다.

이 제한은 멤버 함수와 다른 독립적 인 함수를 불필요하게 만들어 프로그래밍 스타일을 심각하게 경감하므로 STL 스타일의 코드를 작성하기가 더 어려워집니다.

Question

기본 템플릿 인수가 클래스 템플릿에만 허용되는 이유는 무엇입니까? 왜 우리는 멤버 함수 템플릿에 기본 타입을 정의 할 수 없습니까? 예 :

struct mycclass {
  template<class T=int>
  void mymember(T* vec) {
    // ...
  }
};

대신 C ++은 기본 템플릿 인수가 클래스 템플릿에서만 허용되도록합니다.




지금까지, 함수 템플리트에 대한 기본 템플리트 매개 변수의 모든 예는 과부하로 수행 될 수 있습니다.

아라크 :

struct S { 
    template <class R = int> R get_me_R() { return R(); } 
};

될 수 있습니다 :

struct S {
    template <class R> R get_me_R() { return R(); } 
    int get_me_R() { return int(); }
};

내 자신의:

template <int N = 1> int &increment(int &i) { i += N; return i; }

될 수 있습니다 :

template <int N> int &increment(int &i) { i += N; return i; }
int &increment(int &i) { return increment<1>(i); }

litb :

template<typename Iterator, typename Comp = std::less<Iterator> >
void sort(Iterator beg, Iterator end, Comp c = Comp())

될 수 있습니다 :

template<typename Iterator>
void sort(Iterator beg, Iterator end, std::less<Iterator> c = std::less<Iterator>())

template<typename Iterator, typename Comp >
void sort(Iterator beg, Iterator end, Comp c = Comp())

Stroustrup :

template <class T, class U = double>
void f(T t = 0, U u = 0);

가능할 수있는 것 :

template <typename S, typename T> void f(S s = 0, T t = 0);
template <typename S> void f(S s = 0, double t = 0);

나는 다음 코드를 가지고 증명했다.

#include <iostream>
#include <string>
#include <sstream>
#include <ctype.h>

template <typename T> 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 <typename S, typename T> void g(S s, T t){
    std::cout << "f<" << typeid(S).name() << "," << typeid(T).name()
        << ">(" << s << "," << prettify(t) << ")\n";
}


template <typename S, typename T> void f(S s = 0, T t = 0){
    g<S,T>(s,t);
}

template <typename S> void f(S s = 0, double t = 0) {
    g<S,double>(s, t);
}

int main() {
        f(1, 'c');         // f<int,char>(1,'c')
        f(1);              // f<int,double>(1,0)
//        f();               // error: T cannot be deduced
        f<int>();          // f<int,double>(0,0)
        f<int,char>();     // f<int,char>(0,0)
}

인쇄 된 출력은 f에 대한 각 호출의 주석과 일치하며 주석 처리 된 호출은 예상대로 컴파일되지 않습니다.

따라서 기본 템플릿 매개 변수는 "필요하지 않습니다"라고 생각되지만 아마도 기본 함수 인수가 "필요하지 않다"는 동일한 의미에서만 사용됩니다. Stroustrup의 결함 보고서에서 알 수 있듯이, 추론되지 않은 매개 변수를 추가하는 것은 다른 사람이 실현하기에 너무 늦었습니다. 따라서 현재 상황은 표준이 아닌 기능 템플릿 버전을 기반으로 유효합니다.




Windows에서는 모든 버전의 Visual Studio에서이 오류 ( C4519 )를 경고로 변환하거나 다음과 같이 비활성화 할 수 있습니다.

#ifdef  _MSC_VER
#pragma warning(1 : 4519) // convert error C4519 to warning
// #pragma warning(disable : 4519) // disable error C4519
#endif

자세한 내용은 C4519 참조 C4519 .




내가 사용하는 것은 다음 트릭이다.

당신이 다음과 같은 기능을 갖기를 원한다고하자.

template <typename E, typename ARR_E = MyArray_t<E> > void doStuff(ARR_E array)
{
    E one(1);
    array.add( one );
}

당신은 허락되지 않을 것이지만 나는 다음 방법을 사용합니다 :

template <typename T>
struct MyArray_t {
void add(T i) 
{
    // ...
}
};

template <typename E, typename ARR_E = MyArray_t<E> >
class worker {
public:
    /*static - as you wish */ ARR_E* parr_;
    void doStuff(); /* do not make this one static also, MSVC complains */
};

template <typename E, typename ARR_E>
void worker<E, ARR_E>::doStuff()
{
    E one(1);
    parr_->add( one );
}

이렇게하면 다음과 같이 사용할 수 있습니다.

MyArray_t<int> my_array;
worker<int> w;
w.parr_ = &arr;
w.doStuff();

우리는 명시 적으로 두 번째 매개 변수를 설정할 필요가 없음을 알 수 있습니다. 아마 누군가에게 유용 할 것입니다.




C ++ 템플릿 인용하기 : 전체 가이드 (207 페이지) :

템플릿이 원래 C ++ 언어에 추가되었을 때 명시 적 함수 템플릿 인수는 유효한 구문이 아니 었습니다. 함수 템플릿 인수는 항상 호출 식에서 연역적이어야합니다. 결과적으로, 디폴트가 항상 추론 된 값에 의해 무시되기 때문에 기본 함수 템플리트 인수를 허용 할 강력한 이유가없는 것으로 보입니다.