문제

다음과 유사한 방문자 클래스가 있습니다.

struct Visitor 
{
    template <typename T>
    void operator()(T t)
    {
        ...
    }

    void operator()(bool b)
    {
        ...
    }
};

분명히, operator()(bool b) 이전 템플릿 기능을 전문화하기 위한 것입니다.

그러나 그것은 template<> 이전에 보던 구문을 템플릿 전문화로 선언했습니다.하지만 컴파일됩니다.

이거 안전한가요?이 올바른지?

도움이 되었습니까?

해결책

귀하의 코드는 템플릿 전문화가 아니라 템플릿이 아닌 함수입니다.거기에는 몇 가지 차이점이 있습니다.템플릿이 아닌 연산자()는 템플릿 버전보다 우선하지만(정확한 일치를 위해 유형 변환이 발생하지 않음) 템플릿 함수를 강제로 호출할 수 있습니다.

class Visitor
{
public: // corrected as pointed by stefanB, thanks
   template <typename T>
   void operator()( T data ) {
      std::cout << "generic template" << std::endl;
   }
   void operator()( bool data ) {
      std::cout << "regular member function" << std::endl;
   }
};
template <> // Corrected: specialization is a new definition, not a declaration, thanks again stefanB 
void Visitor::operator()( int data ) {
   std::cout << "specialization" << std::endl;
}
int main()
{
   Visitor v;
   v( 5 ); // specialization
   v( true ); // regular member function
   v.operator()<bool>( true ); // generic template even if there is a non-templated overload
   // operator() must be specified there (signature of the method) for the compiler to 
   //    detect what part is a template. You cannot use <> right after a variable name
}

코드에는 큰 차이가 없지만 코드가 템플릿 매개변수 유형을 전달해야 한다면 더 재미있어질 것입니다.

template <typename T>
T g() { 
   return T();
}
template <>
int g() {
   return 0;
}
int g() {
   return 1;
}
int main()
{
   g<double>(); // return 0.0
   g<int>(); // return 0
   g(); // return 1 -- non-templated functions take precedence over templated ones
}

다른 팁

여기에있는 것은 기능 과부하입니다. 템플릿 전문화를 얻으려면 실제로 필요합니다 template <> 통사론. 그러나이 두 가지 접근 방식은 동일하게 보일 수 있지만 미묘하게 다르며 호출 할 올바른 기능을 선택할 때 컴파일러도 손실 될 수 있음을 알고 있어야합니다. 가능한 모든 사례를 나열하는 것은이 답변에 너무 길지만 확인하고 싶을 수도 있습니다. 허브 셔터 gotw #49 주제에.

아, 컴파일 할거야. 템플릿 기능이 아닙니다. 템플릿 전문화 대신 정기적 인 비 템플릿 기능이 있습니다.

그것은 안전하고 실제로 당신이 원하는 것도 가능성이 높습니다. 방문자 패턴은 일반적으로 과부하로 구현됩니다. 기능 템플릿 전문 어쨌든 정말 좋은 생각이 아닙니다.

당신이 한 일은 템플릿 직렬화가 아니라 기능 과부하입니다. 그것은 안전하다.

추신 : 당신이 달성하려는 것을 알지 못하고 그것이 맞는지 여부를 말하기는 어렵습니다. 템플릿 또는 과부하 기능이든 상관없이 운영자는 컴파일 시간으로 선택됩니다. 런타임 파견이 필요한 경우 과부하가 아닌 다형성이 필요합니다. 글쎄, 당신은 어쨌든 그것을 알고있을 것입니다. 만일을 대비하여.

당신은 가지고 있습니다

  • void operator()(bool b) 그것은 비 템플릿 기능입니다
  • template< typename T > void operator()(T t) 위의 내용을 과부하시키는 별도의 기본 템플릿입니다.

당신은 template<> void operator(int i) 이는 단지 고려됩니다 void operator()(bool b) 일치하지 않았습니다.

기본 템플릿의 전문화는 호출 할 기본 템플릿 메소드를 선택하는 데 사용됩니다. 그러나 귀하의 경우 먼저 고려할 수없는 비 모전 방법이 있습니다.

기사 기능 템플릿을 전문화하지 않는 이유는 무엇입니까? 방법이 어떻게 선택되는지에 대한 좋은 설명을 제공합니다.

Sumary :

  1. 비 템플릿 함수는 먼저 고려됩니다 (위의 일반 연산자 () (BOOL)입니다.
  2. 기능베이스 템플릿이 두 번째로 확인됩니다 (이것은 템플릿 기능입니다), 가장 특수화 된 기본 선 판이 선택 된 다음 특수화가 사용되는 정확한 유형에 대한 전문화가있는 경우 기본 템플릿은 '올바른'유형과 함께 사용됩니다 (참조). 기사의 설명)

예시:

#include <iostream>
using namespace std;

struct doh
{
    void operator()(bool b)
    {
        cout << "operator()(bool b)" << endl;
    }

    template< typename T > void operator()(T t)
    {
        cout << "template <typename T> void operator()(T t)" << endl;
    }
};
// note can't specialize inline, have to declare outside of the class body
template<> void doh::operator()<>(int i)
{
    cout << "template <> void operator()<>(int i)" << endl;
}
template<> void doh::operator()<>(bool b)
{
    cout << "template <> void operator()<>(bool b)" << endl;
}

int main()
{
    doh d;
    int i;
    bool b;
    d(b);
    d(i);
}

전화를받습니다.

operator()(bool b)       <-- first non template method that matches
template <> void operator()(int i)     <-- the most specialized specialization of templated function is called
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top