2011-05-03 45 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 2011-05-03 12:35:49

+0

@AtoMerZ是的,你可以叫它;名稱'helper'將在包含頭文件的任何源文件中定義。它應該是隱藏的,所以只有'func1'和'func2'知道它存在,而其餘的程序不會。 – Jesper 2011-05-03 12:38:49

+0

@Jsper,我推薦John Dibling的方法。 – atoMerz 2011-05-03 12:40:49

回答

18

(如在許多Boost庫用於例如)一種常見的方法是把輔助在一個叫做details命名空間,有可能在一個單獨的標題(從「公共」報頭包括在內)。

有沒有辦法來防止它被看見,並且可贖回,不過這很清楚地表明,它是實現,而不是接口的一部分。

+0

+1將其稱爲「公共」標題。 – xtofl 2011-05-03 13:36:55

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 2011-05-03 12:47:25

+0

@Jesper:就是這一點。 – xtofl 2011-05-03 13:00:11

+0

然後我不明白你的答案。僅僅是爲了展示一種行不通的方式,或者它是一種解決方案? – Jesper 2011-05-03 13:15:37

4

兩個選項了我的頭頂部:

  1. 將所有執行到您包括您的H文件底部的HPP文件。
  2. 將您的代碼重構爲類模板,然後使幫助器變爲私有。
+3

我不明白第一個選項如何解決任何問題。該hpp文件仍將包含在編譯單元中,您在其中聲明的任何內容在包含它的源文件中仍然可見。 – Jesper 2011-05-03 12:44:07

3

所建立的先例是把那種事情在一個專門(即一致)命名的嵌套命名空間。 Boost使用namespace details,Loki使用namespace Private。顯然,沒有什麼可以阻止利用這些空間中的內容,但是這兩個名字傳達其內容並非用於一般消費的意義。

也就是說,一個簡單的選擇是將func1func2從自由函數模板轉換爲某些常用類的靜態成員函數模板;這樣一來,helper可以簡單地說類的私有成員,看不見外面的世界:

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 
} 

那麼爲什麼有人想要這樣?因爲具有完全相同的不同實例是您可能不想要的。當編譯器告訴你一些類的構造函數是私有的,那麼你可以認爲具有不同的實例將是不必要的。