2011-05-03 47 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 
} 

那么为什么有人想要这样?因为具有完全相同的不同实例是您可能不想要的。当编译器告诉你一些类的构造函数是私有的,那么你可以认为具有不同的实例将是不必要的。