【问题标题】:Inlining a function template specialization内联函数模板特化
【发布时间】:2014-02-04 17:26:42
【问题描述】:

以下代码位于 .h 文件中(带有包含保护)

template<typename T1, typename T2> // a
void func(T1 const &t1, T2 const &t2)
{
    std::cout << "\nbase template"; 
}

template<> // b
inline void func<int, int>(int const &t1, int const &t2)
{
    std::cout << "\nspecialization for integers";
}

当从 (b) 中删除内联关键字时,以下代码(从包含 .h 的 .cpp 调用)将无法编译

func<int, int>(1, 2);

emmiting a linker error " error LNK2005: "void __cdecl func(int const &,int const &)" (??$func@HH@@YAXABH0@Z) 已在 ConsoleApplication1.obj 中定义"

为什么会这样?

编辑:

因此,既然它们是定义(由 Luchian Grigore 回答),显式特化是否意味着显式实例化,还是此编译器特定于?

【问题讨论】:

    标签: c++


    【解决方案1】:

    因为显式特化是定义,因此在多个翻译单元中包含该文件会导致多次定义符号,这违反了一个定义规则。

    除了将其标记为inline,您还可以将声明留在标题中并将定义移动到实现文件中。

    【讨论】:

    • 感谢内联的替代品!
    【解决方案2】:

    你只能直接用类型本身重载它,不需要写模板:

    void func(int const &t1, int const &t2)
    {
        std::cout << "\nspecialization for integers";
    }
    

    现在,发生错误是因为如果在头文件中定义该函数,如果包含头文件,则该函数最终会出现在两个 cpp 文件中,因此将有两个相同函数的声明(如错误所说:already defined)导致链接错误。为了解决这个问题,只需在没有实现的情况下在头文件中编写声明并将实现移动到一个头文件中:

    //header
    void func(int const &t1, int const &t2);
    
    //cpp file
    void func(int const &t1, int const &t2)
    {
    ...
    }
    

    【讨论】:

    • 函数模板可以明确专门化,你不应该但你可以(gotw.ca/publications/mill17.htm),它与重载有本质的不同(请参考链接并重新考虑你的答案)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    • 2018-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多