2013-09-02 3 views
9

stackoverflow 내 많은 질문에 대한 답변을 찾은 후에, 나는 지금 내가 대답을 찾을 수없는 질문에 대해오고 누군가가 나를 도울 수 있기를 바랍니다!함수 템플릿 특수화가 클래스 내부에서 허용되지 않는 이유는 무엇입니까?

제 문제는 C++ 클래스의 함수 내에서 명시적인 템플릿 화를하고 싶다는 것입니다. 내 컴파일러 (g ++) 및 C++ 표준 (14.7.3)에서이 전문은 클래스가 선언 된 네임 스페이스에서 수행되어야한다는 것을 알려줍니다. 이것은 내가 전문화를 수업에 넣을 수는 없다는 것을 의미하는 것으로 이해하지만이 제한의 요지는 보이지 않는다! 전문화가 수업 내에서 이루어지지 않도록하는 좋은 이유가 있는지 아는 사람이 있습니까?

해결 방법이 있다는 것을 알고 있습니다. 구조체 안에 함수를 넣으려고하지만 언어에 왜이 디자인이 있는지 이해하고 싶습니다. 클래스 내에 특수 기능을 허용하지 않는 좋은 이유가 있다면, 해결하기 전에 알아야한다고 생각합니다.

미리 감사드립니다. 내가하고 싶은 것을 설명하는 다음 시험 예에서 일부 코드는 다음과 같습니다 : 내 질문에 조금 더 정확한 만들려면


이 불가능

#include <cstdio> 

namespace MalinTester { 

template <size_t DIMENSIONALITY> 
class SpecializationTest { 
public: 
    SpecializationTest() { 
     privateVariable = 5; 
    }; 
    virtual ~SpecializationTest() {}; 

    void execute() { 
     execute<DIMENSIONALITY>(); 
    }; 

private: 
    int privateVariable; 
    template <size_t currentDim> 
    static void execute() { 
     printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable); 
     execute<currentDim-1>(); 
    } 

    template <> 
    static void execute<0>() { 
     printf("This is the base case. Current dim is 0.\n"); 
    } 

}; 

; g ++는 말한다 :

#include <cstdio> 

namespace MalinTester { 

    template <size_t DIMENSIONALITY> class SpecializationTest {}; 

    template <size_t currentDim> 
    void execute() { 
     printf("This is the general case. Current dim is %d. The private variable is %d.\n", currentDim, privateVariable); 
     execute<currentDim-1>(); 
    } 

    template <> 
    void execute<0>() { 
     printf("This is the base case. Current dim is 0.\n"); 
    } 

    template <size_t DIMENSIONALITY> 
    class SpecializationTest { 
    public: 
     SpecializationTest() {}; 
     virtual ~SpecializationTest() {}; 

     void execute() { 
      MalinTester::execute<DIMENSIONALITY>(); 
     }; 
    private: 
     int privateVariable = 5; 
    }; 
}; 
}; 

내가 실행의 플릿 버전 privatevariable 사용할 수 없습니다 : 나는 함수가 이름 공간 MalinTester에서 클래스 외부 실행 넣으면

SpecializationTest_fcn.h:27: error: explicit specialization in non-namespace scope ‘class MalinTester::SpecializationTest<DIMENSIONALITY>’ 
SpecializationTest_fcn.h:28: error: template-id ‘execute<0>’ in declaration of primary template 

, 그것은 다음과 같이 표시됩니다 , 그것은 수업에서 사적인 것입니다. 정말 개인을 원합니다. 가능한 한 내 데이터를 캡슐화하고 싶습니다.

물론 함수에 인수로 privateVariable을 보낼 수는 있지만이 문제를 피하는 것이 더 아름답다고 생각합니다. C++ 표준에 명시 적 전문화를 허용하지 않는 것이 좋은 이유가 있다면 정말 궁금합니다. 위의 첫 번째 코드 예제와 같습니다.


@Arne Mertz : 이것은 제가 시도한 해결 방법이지만 privateVariable 사용도 허용하지 않습니다. 그리고 무엇보다도, 이렇게하는 것이 좋은 생각인지 궁금합니다. 멤버 함수를 특수화 할 수 없으므로 클래스 내부의 구조체에 캡슐화 된 함수의 특수화를 수행해서는 안됩니다.

#include <cstdio> 

namespace MalinTester { 

template <size_t DIMENSIONALITY> 
class SpecializationTest { 
public: 
    SpecializationTest() { 
     privateVariable = 5; 
    }; 
    virtual ~SpecializationTest() {}; 

    void execute() { 
     Loop<DIMENSIONALITY, 0>::execute(); 
    }; 

private: 
    int privateVariable; 

    template <size_t currentDim, size_t DUMMY> 
    struct Loop { 
     static void execute() { 
      printf("This is the general case. Current dim is %d.\n", currentDim); 
      Loop<currentDim-1, 0>::execute(); 
     } 
    }; 

    template <size_t DUMMY> 
    struct Loop<0, DUMMY> { 
     static void execute() { 
      printf("This is the base case. Current dim is 0.\n"); 
     } 
    }; 
}; 
}; 
+0

관련성이 높습니다. http://stackoverflow.com/questions/18294990/why-can-templatet-but-not-template-be-defined-outside-of-a-namespace-block/ – Rapptz

+0

해결할 정확한 문제는 무엇입니까? 네임 스페이스에 전문화를 넣을 수는 없습니까? –

+0

n.m .: 함수에서 클래스의 인스턴스 변수를 사용하고 싶습니다. 클래스 외부의 네임 스페이스에 특수화를 추가하면 해당 함수에 대한 액세스 권한이 없습니다 (실제 클래스의 인스턴스를 함수의 인수로 보내지 않으면 내 생각에 코드가 더 못 생깁니다).) – Malin

답변

3

자료 전문 : .H에서

:

같은 네임 스페이스에서 통화 당에서
template <class T> 
class UISelectorSlider : public UISelectorFromRange<T> { 
public: 
    UISelectorSlider(); 
    virtual ~UISelectorSlider(); 
private: 
    float width; 
    float getPositionFromValue(T value); 
}; 

:

template <> 
float UISelectorSlider<MVHue>::getPositionFromValue(MVHue value) 
{ 
    return width * (float)value/360.0; 
} 

당신은 전문 클래스 내의 전문 기능을 원하는 경우 :

내부 클래스 추가 (.H) (개인 기능) : 통화 당 내부

private: 
    template <int I> 
    void foo(); 

전문화 :

template <> 
template <> 
void UISelectorSlider<MVHue>::foo<3>() 
{ 
    // you can access private fields here 
} 

UPDATE :

그러나이 같은 쓰기 어차피 :

template <class T> 
template <> 
void UISelectorSlider<T>::foo<3>() 
{ 
    // you can access private fields here 
} 

당신은 얻을 것이다 : 오류 : 둘러싼 클래스 템플릿이 명시 적으로 특수화되지 않았습니다.

클래스 또는 네임 스페이스 내부에서이 정의가 중요하지 않습니다. 핵심은 정확한 부분 전문화가 아니라는 것입니다.이 함수는 컨텍스트 클래스 (호출하려는 멤버)를 정의하지 않았습니다. 다른 말로하면 - 멤버를 전문화하면 실제로 클래스를 포함하는 전체를 전문화하지만 멤버 자체는 전문화하지 마십시오. 컴파일러는 클래스가 아직 완전히 정의되지 않았기 때문에이를 수행 할 수 없습니다. 따라서 이것은 템플릿 디자인에 의한 제한입니다. 그리고 실제로 작동한다면 템플릿은 간단한 매크로와 동등합니다. (아마도 매크로 매직으로 작업을 해결할 수 있습니다.)

+2

사람들이 기꺼이 대답 해 주셔서 감사합니다.하지만 ** 내 질문은 ** 클래스 내에서 templatized 함수의 특수화를 허용하지 않는 표준에 대한 좋은 이유가 있다면 ** 해결 방법이 아닌 **입니다. (또한, 클래스의 함수를 캡슐화하고 싶습니다!) – Malin

+0

죄송합니다, 지금 귀하의 문제를 이해 (및 수정 된 답변). –

+0

OK, 감사합니다 !! – Malin

관련 문제