有效C++
Analyze
,对一系列数据进行分析。这个函数是用不同类型的迭代器从几个地方调用的,所以我把它做成了一个模板(并在头文件中实现了它)。函数依赖于静态数据表,
AnalysisTable
,我不想暴露给代码的其余部分。
我的第一个方法是把桌子做成一张桌子
static const
里面
Analysis
namespace MyNamespace {
template <typename InputIterator>
int Analyze(InputIterator begin, InputIterator end) {
static const int AnalysisTable[] = { /* data */ };
... // implementation uses AnalysisTable
return result;
}
} // namespace MyNamespace
编译器似乎创建了
分析表
对于的每个实例化
分析
,这是浪费空间(在小的程度上,也是浪费时间)。
所以我把表移到函数外,像这样:
namespace MyNamespace {
const int AnalysisTable[] = { /* data */ };
template <typename InputIterator>
int Analyze(InputIterator begin, InputIterator end) {
... // implementation uses AnalysisTable
return result;
}
} // namespace MyNamespace
现在只有一个表的副本,但它暴露在其余代码中。我宁愿隐藏这个实现细节,所以我引入了一个未命名的命名空间:
namespace MyNamespace {
namespace { // unnamed to hide AnalysisTable
const int AnalysisTable[] = { /* data */ };
} // unnamed namespace
template <typename InputIterator>
int Analyze(InputIterator begin, InputIterator end) {
... // implementation uses AnalysisTable
return result;
}
} // namespace MyNamespace
但是现在我又有了这个表的多个副本,因为包含这个头文件的每个编译单元都有自己的副本。如果
如果不是模板,我可以将所有实现细节从头文件中移出。但它是一个模板,所以我似乎卡住了。
我的下一个尝试是将表放在实现文件中并
extern
内声明
.
// foo.h ------
namespace MyNamespace {
template <typename InputIterator>
int Analyze(InputIterator begin, InputIterator end) {
extern const int AnalysisTable[];
... // implementation uses AnalysisTable
return result;
}
} // namespace MyNamespace
// foo.cpp ------
#include "foo.h"
namespace MyNamespace {
const int AnalysisTable[] = { /* data */ };
}
这看起来应该是可行的,而且——事实上——编译器很满意。然而,链接器抱怨说,“未解析的外部符号
我唯一能想到的是给内部命名空间起一个名字,在头中声明表,并在实现文件中提供实际数据:
// foo.h -----
namespace MyNamespace {
namespace PrivateStuff {
extern const int AnalysisTable[];
} // unnamed namespace
template <typename InputIterator>
int Analyze(InputIterator begin, InputIterator end) {
... // implementation uses PrivateStuff::AnalysisTable
return result;
}
} // namespace MyNamespace
// foo.cpp -----
#include "foo.h"
namespace MyNamespace {
namespace PrivateStuff {
const int AnalysisTable[] = { /* data */ };
}
}
再一次,我正好有一个
分析表
(耶!),但是程序的其他部分可以访问它(boo!)。内部名称空间使得它们
不应该
,但还是有可能的。
有没有可能有一个表的实例,并将表移动到除了
分析
?