简体   繁体   English

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

[英]hide function template, declare specializations

This is a followup to C++ templates: prevent instantiation of base template 这是C ++模板的后续内容:防止实例化基本模板

I use templates to achieve function overloading without the mess of implicit type conversions: declare the function template, define desired specializations (overloads). 我使用模板来实现函数重载,而不会造成隐式类型转换的麻烦: 声明函数模板,定义所需的专业化(重载)。 all is well except wrong code does not produce errors until the link phase: 一切正常,除非错误的代码在链接阶段之前不会产生错误:

lib.hpp: lib.hpp:

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

lib.cpp: lib.cpp:

#include "lib.hpp"

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

main.cpp: main.cpp中:

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

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

gcc output: 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)'

I'd like to have it fail during compilation of main.cpp. 我想在main.cpp编译期间使它失败。 Can I somehow declare only specializations actually implemented? 我可以以某种方式声明仅实际实施的专业化课程吗?

What are my options? 我有什么选择? The target is C++03, and I'm mainly interested in gcc-4.x and VC9. 目标是C ++ 03,我主要对gcc-4.x和VC9感兴趣。

It seems to produce a linker error even if you don't put it in the separate file. 即使不将其放在单独的文件中,它似乎也会产生链接器错误。

However, to produce a compiler error for other instantiations, implement the function and use a compile-time assertion, eg 但是,要为其他实例产生编译器错误,请实现该函数并使用编译时断言,例如

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

And just for general information, C++0x has a much more elegant way to deal with it: 仅作为一般信息,C ++ 0x拥有一种更为优雅的处理方式:

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

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

The best way is to implement that basic template with something invalid (not illegal) C++ code. 最好的方法是使用无效的(不是非法的)C ++代码来实现该基本模板。 For example, 例如,

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

This error will be compile time; 该错误将是编译时; and it's generated only when you instantiate any version other than 'long' & 'bool'. 并且仅当您实例化“ long”和“ bool”以外的任何版本时才生成。 If you don't instantiate 'int' version, compilation will go fine. 如果您不实例化“ int”版本,则编译会很好。

I don't believe it's possible to do what you want. 我不相信您可以做自己想做的事情。 See these FAQs for more info: 有关更多信息,请参见以下常见问题解答:

How can I avoid linker errors with my template functions? 如何避免模板函数出现链接器错误?

How can I avoid linker errors with my template classes? 如何避免模板类出现链接器错误?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM