隐藏功能模板,声明专业化

时间:2010-01-28 15:13:06

标签: c++ templates declaration template-specialization

这是C++ templates: prevent instantiation of base template

的后续内容

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

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; }

main.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 个答案:

答案 0 :(得分: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; }

答案 1 :(得分:1)

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

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

此错误将是编译时间;并且仅当您实例化除“long”之外的任何版本时才会生成它。 'bool的'。如果你没有实例化'int'版本,编译就可以了。

答案 2 :(得分:0)

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

How can I avoid linker errors with my template functions?

How can I avoid linker errors with my template classes?

答案 3 :(得分:0)

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