C++函数模板特化导致的多重定义链接错误

原创
小哥 2年前 (2023-05-25) 阅读数 5 #大杂烩

转载请注明文章: C++ 函数模板专用导致的多个定义链接错误 出处: 多客博图

标题可能不是很清楚。为了解释,函数模板通常放置在头文件中,因此有时我也会进行专门化并将其包含在此头文件中。当此头文件包含多个时,链接多个定义时会出现错误。我举一个例子如下:

现象描述

有文件"header.h"

#ifndef HEADER
#define HEADER

template 
size_t size_rb_tree_node()
{
    return 20; /*constant value for l r p pointer and (color & height) and void * value*/
}

template <>
size_t size_rb_tree_node()
{
    return 30;
}

#endif

"Source.cpp"

#include "Header.h"

int count()
{
    int a = size_rb_tree_node();

    return a;
}

"main.cpp"

#include "Header.h"

using namespace std;

int count();

int main()
{
    int a = size_rb_tree_node();
    a = size_rb_tree_node();
}

编译后,链接时报错:

1>------ Build started: Project: Win32Project1, Configuration: Debug Win32 ------
1>  AllocatorNew.cpp
1>Source.obj : error LNK2005: "unsigned int __cdecl size_rb_tree_node(void)" (??$size_rb_tree_node@PAX@@YAIXZ) already defined in AllocatorNew.obj
1>C:Users   ianzuozDocumentsVisual Studio 2012ProjectsWin32Project1DebugWin32Project1.exe : fatal error LNK1169: one or more multiply defined symbols found
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

其实原因很简单了,因为特化后的函数就是一个普通函数,这个和在一个头文件里面定义一个函数,然后多出include与此头文件相同的结果将导致多个定义。

解决方法

1添加专用函数inline标记,以便编译器不会为此函数生成函数符号,只需将其视为宏扩展即可。但是,某些编译器不一定inline的。行不行试试就知道了,如下:

#ifndef HEADER
#define HEADER

template 
size_t size_rb_tree_node()
{
    return 20; /*constant value for l r p pointer and (color & height) and void * value*/
}

template <>
inline size_t size_rb_tree_node()
{
    return 30;
}

#endif

2将此函数设置为文件域,这意味着它不参与全局link也可以:

#ifndef HEADER
#define HEADER

template 
size_t size_rb_tree_node()
{
    return 20; /*constant value for l r p pointer and (color & height) and void * value*/
}

template <>
static size_t size_rb_tree_node()
{
    return 30;
}

#endif

3另一种方法是从原始文件中取出此专用化,将其放在所需的实现文件中,然后添加它static属性。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除