2011-05-03 3 views
16

내가 헤더 파일에 선언 된 두 개의 템플릿 함수가 있다고 가정하자 :구현 도우미 템플릿을 숨기는 방법은 무엇입니까?

template <typename T> void func1(const T& value); 
template <typename T> void func2(const T& value); 

그리고 이러한 기능의 구현 (또한 헤더 파일이 아닌 소스 파일에서, 그들은 템플릿 때문에이) 일부를 사용하는 가정 구현 도우미 함수는 템플릿이기도합니다.

template <typename T> void helper(const T& value) { 
    // ... 
} 

template <typename T> void func1(const T& value) { 
    // ... 
    helper(value); 
} 

template <typename T> void func2(const T& value) { 
    // ... 
    helper(value); 
} 

헤더 파일을 포함하는 모든 소스 파일에서 도우미 함수가 표시됩니다. 도우미 기능은 구현 세부 사항이기 때문에 나는 그것을 원하지 않습니다. 도우미 기능을 숨기는 방법이 있습니까?

+0

눈에 띄는 것은 무엇입니까? 전화 할 수있는 것처럼? – atoMerz

+0

@AtoMerZ 예, 호출 할 수 있습니다. 'helper'라는 이름은 헤더 파일을 포함하는 모든 소스 파일에 정의됩니다. 숨겨져 있어야만 func1과 func2만이 존재한다는 것을 알 수 있고, 프로그램의 나머지 부분은 존재하지 않는다. – Jesper

+0

@Jsper, John Dibling의 접근 방식을 권하고 싶습니다. – atoMerz

답변

18

(예를 들어, 많은 부스트 ​​라이브러리에서 사용) 일반적인 방법은 아마도 (이하 "공공"헤더 포함) 별도의 헤더에, details라는 네임 스페이스의 도우미를 배치하는 것입니다.

표시되지 않도록하고 호출 할 수 없도록하는 방법은 없지만 인터페이스가 아니라 구현의 일부임을 명확하게 나타냅니다.

+0

+1을 'public'헤더라고 부릅니다. – xtofl

3

코드 사용자가 func1 함수의 전체 정의를 볼 필요가 있으므로 구현 또는 도우미 함수 구현이 숨겨져있을 수 없습니다.

//templates.h 
template< typename T > void f1(T&); 

#include <templates_impl.h> // post-inclusion 

그리고 정의 :

// templates_impl.h 
template< typename T > void f1_helper(T&) { 
} 

template< typename T > void f1(T&) { 
    // the function body 
} 
+0

나는 이것이 작동한다고 생각하지 않는다. 내'.cpp' 파일에서'templates.h'를 포함 시키면'templates_impl.h'도 포함됩니다 (간접적 임에도 불구하고). 그 내용은 내'.cpp' 파일에서 볼 수 있습니다 - 그래서'f1_helper()' 숨어 있지 않습니다. – Jesper

+0

@Jesper : 그게 핵심입니다. – xtofl

+0

나는 당신의 대답을 이해하지 못합니다. 작동하지 않는 방법을 시연하는 것입니까 아니면 해결책입니까? – Jesper

4
당신이 에 다른 파일를 구현을 이동하는 경우

는하지만, 사용자는와 템플릿 선언에 직면 할 것이다

내 머리 꼭대기의 두 가지 옵션 :

  1. 모든 구현을 h 파일의 맨 아래에 포함 된 hpp 파일로 이동하십시오.
  2. 코드를 클래스 템플릿으로 리팩터링 한 다음 헬퍼를 비공개로 설정하십시오.
+3

첫 번째 옵션으로 어떻게 문제가 해결되는지는 알 수 없습니다. 그 hpp 파일은 여전히 ​​컴파일 유닛에 포함될 것입니다. 거기에 선언 한 내용은 소스 파일에 계속 표시됩니다. – Jesper

3

확립 된 선례는 특수하게 (즉 일관되게) 명명 된 중첩 네임 스페이스에 그러한 종류의 것을 넣는 것입니다. 부스트는 namespace details을 사용하고 Loki는 namespace Private을 사용합니다. 분명히 아무 것도 수 없습니다 사람이 그 네임 스페이스의 내용을 사용하지 못하게하지만, 두 가지 이름은 그 내용이 일반적인 소비를위한 것이 아니라는 의미를 전달합니다.

즉, 쉬운 대안은 자유 함수 템플릿에서 func1func2을 몇 가지 공통 클래스의 정적 멤버 함수 템플릿으로 바꾸는 것입니다. 이 방법은, helper은 단순히 외부 세계에 눈에 보이지 않는 말했다 클래스의 private 멤버가 될 수 있습니다 :

struct funcs { 
    template<typename T> 
    static void func1(T const& value) { 
     // ... 
     helper(value); 
    } 

    template<typename T> 
    static void func2(T const& value) { 
     // ... 
     helper(value); 
    } 

private: 
    template<typename T> 
    static void helper(T const& value) { 
     // ... 
    } 
}; 
1

내가하는 모든 기능이 정적 및 도우미 기능을 비공개로, 템플릿 클래스를 만들 (전에 말했듯이).아래 그림과 같이하지만 그 외에 또한 생성자 개인을 권 해드립니다 : 생성자는 비공개로 할 때

template <typename T> 
class Foo{ 
public: 
    static void func1(const T& value); 
    static void func2(const T& value); 
private: 
    Foo(); 
    static void helper(const T& value); 
} 

는, 컴파일러는이 템플릿 클래스의 인스턴스를 허용하지 않습니다. 따라서 아래의 코드는 불법이됩니다.

#include "foo.h" 

int main(){ 
    int number = 0; 
    Foo<int>::func1(number); //allowed 
    Foo<int>::func2(number); //allowed 
    Foo<int>::helper(number); //not allowed, because it's private 
    Foo<int> foo_instance; //not allowed, because it's private 
} 

왜 누군가가 이것을 원할까요? 정확히 똑같은 다른 인스턴스를 갖는 것은 아마도 당신이 원하지 않는 무언가이기 때문입니다. 컴파일러가 어떤 클래스의 생성자가 private이라고 알려주면, 다른 인스턴스를 가지는 것이 불필요하다고 생각할 수 있습니다.

관련 문제