关于c ++:隐藏功能模板,声明专业化

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++代码来实现这个基本模板。例如,

template T f(T v) { return v.Default_Implementation_Not_Available; }

此错误将在编译时出现;只有在实例化"long"和"bool"以外的任何版本时才会生成。如果不实例化"int"版本,编译将正常进行。


编译main.cpp时,编译器无法知道其他编译单元中可能存在哪些模板专门化——因此在编译时无法标记此错误,必须等到链接时再进行标记。


我不相信做你想做的事是可能的。有关详细信息,请参阅以下常见问题解答:

如何避免模板函数出现链接器错误?

如何避免模板类出现链接器错误?