2

这是C++ 模板的后续:防止基模板的实例化

我使用模板来实现函数重载,而不会出现隐式类型转换的混乱:声明函数模板,定义所需的特化(重载)。一切都很好,除了错误的代码在链接阶段之前不会产生错误:

lib.hpp:

template<class T> T f(T v);

lib.cpp:

#include "lib.hpp"

template<> long f(long v) { return -v; }
template<> bool f(bool v) { return !v; }

主.cpp:

#include <iostream>
#include "lib.hpp"

int main()
{
    std::cout
        << f(123L) << ", "
        << f(true) << ", "
        << f(234) << "\n"
    ;
}

gcc 输出:

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感兴趣。

4

4 回答 4

5

即使您不将其放在单独的文件中,它似乎也会产生链接器错误。

但是,要为其他实例产生编译器错误,请实现该函数并使用编译时断言,例如

#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 有一种更优雅的方式来处理它:

template <class T> T f(T) = delete;

template<> long f(long v) { return -v; }
template<> bool f(bool v) { return !v; }
于 2010-01-28T15:48:54.617 回答
1

最好的方法是使用无效(非非法)的 C++ 代码来实现该基本模板。例如,

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

这个错误将是编译时;并且它仅在您实例化“long”和“bool”以外的任何版本时生成。如果你不实例化'int'版本,编译会很好。

于 2011-01-23T11:37:17.557 回答
0

我不相信有可能做你想做的事。有关更多信息,请参阅这些常见问题解答:

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

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

于 2010-01-28T15:31:06.390 回答
0

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

于 2010-01-28T15:31:45.530 回答