hide function template, declare specializations
下面是C++模板:防止基础模板的实例化
我使用模板来实现函数重载,而不需要混乱的隐式类型转换:声明函数模板,定义所需的专门化(重载)。除了错误的代码,所有的都很好,直到链接阶段才会产生错误:
LIB HPP:
1 | template<class T> T f(T v); |
LIB CPP:
1 2 3 4 | #include"lib.hpp" template<> long f(long v) { return -v; } template<> bool f(bool v) { return !v; } |
MCP.CPP:
1 2 3 4 5 6 7 8 9 10 11 12 | #include <iostream> #include"lib.hpp" int main() { std::cout << f(123L) <<"," << f(true) <<"," << f(234) <<" " ; } |
GCC输出:
1 2 3 4 5 | c++ -O2 -pipe -c main.cpp c++ -O2 -pipe -c lib.cpp c++ main.o lib.o -o main main.o(.text+0x94): In function `main': : undefined reference to `int get<int>(int)' |
我希望它在编译main.cpp时失败。我可以以某种方式声明实际实现的专门化吗?
我有什么选择?目标是C++ 03,我主要感兴趣的是GCC-4.x和VC9。
它似乎会产生一个链接器错误,即使你不把它放在单独的文件中。
但是,要为其他实例化生成编译器错误,请实现该函数并使用编译时断言,例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <boost/static_assert.hpp> template <class T> T f(T) { //assert some type-dependent"always-false" condition, //so it won't be triggered unless this function is instantiated BOOST_STATIC_ASSERT(sizeof(T) == 0 &&"Only long or bool are available"); } template<> long f(long v) { return -v; } template<> bool f(bool v) { return !v; } int main() { //f(100); f(100L); f(false); } |
而对于一般信息,C++0X有一个更优雅的方式来处理它:
1 2 3 4 | template <class T> T f(T) = delete; template<> long f(long v) { return -v; } template<> bool f(bool v) { return !v; } |
最好的方法是用无效的(不违法的)C++代码来实现这个基本模板。例如,
此错误将在编译时出现;只有在实例化"long"和"bool"以外的任何版本时才会生成。如果不实例化"int"版本,编译将正常进行。
编译main.cpp时,编译器无法知道其他编译单元中可能存在哪些模板专门化——因此在编译时无法标记此错误,必须等到链接时再进行标记。
我不相信做你想做的事是可能的。有关详细信息,请参阅以下常见问题解答:
如何避免模板函数出现链接器错误?
如何避免模板类出现链接器错误?