代码之家  ›  专栏  ›  技术社区  ›  just somebody

隐藏函数模板,声明专用化

  •  2
  • just somebody  · 技术社区  · 14 年前

    这是对 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; }
    

    MCP.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 回复  |  直到 11 年前
        1
  •  5
  •   UncleBens    14 年前

    它似乎会产生一个链接器错误,即使你不把它放在单独的文件中。

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

    #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; }
    
        2
  •  1
  •   RiaD    11 年前

    最好的方法是用无效的(不违法的)C++代码来实现这个基本模板。例如,

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

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

        3
  •  0
  •   metal    14 年前

    我不相信你想做什么就做什么。有关更多信息,请参阅以下常见问题解答:

    How can I avoid linker errors with my template functions?

    How can I avoid linker errors with my template classes?

        4
  •  0
  •   Martin B    14 年前

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