【问题标题】:How can I resolve this one or more multiply defined symbol found error?如何解决这个一个或多个多重定义符号发现错误?
【发布时间】:2021-12-15 02:34:56
【问题描述】:

以下项目中的错误是什么?

ma​​in.cpp

#include "template_specialization_conflict_test.hpp"

int main()
{
    std::cout << utils::my_template_function(0.555);
    std::cout<<utils::my_template_function<double>(0.555);
    return 0;
}

template_specialization_conflict_test.hpp

#ifndef UTILS__UTILS__UTILS__UTILS
#define UTILS__UTILS__UTILS__UTILS
#include <iostream>

namespace utils
{
    // A generic function
    template <class T>
    T my_template_function(T parameter)
    {
        std::cout << "function template";
        std::cout << parameter;
        return parameter;
    }

    // Template Specialization
    //      A function specialized for double data type
    template <>
    double my_template_function<double>(double parameter)
    {
        std::cout << "function specialization on double";
        std::cout << parameter;
        return parameter;
    }
}
#endif

template_specialization_conflict_test.cpp

#include "template_specialization_conflict_test.hpp"

namespace utils
{
    //empty
}

错误

>------ Rebuild All started: Project: template_specialization_conflict_test, Configuration: x64-Debug ------
  [1/1] Cleaning all built files...
  Cleaning... 2 files.
  [1/3] Building CXX object CMakeFiles\template_specialization_conflict_test.dir\main.cpp.obj
  [2/3] Building CXX object CMakeFiles\template_specialization_conflict_test.dir\template_specialization_conflict_test.cpp.obj
  [3/3] Linking CXX executable template_specialization_conflict_test.exe
  FAILED: template_specialization_conflict_test.exe 
  cmd.exe /C "cd . && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_exe --intdir=CMakeFiles\template_specialization_conflict_test.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\10.0.17763.0\x64\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\10.0.17763.0\x64\mt.exe --manifests  -- "C:\PROGRA~2\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\link.exe" /nologo CMakeFiles\template_specialization_conflict_test.dir\template_specialization_conflict_test.cpp.obj CMakeFiles\template_specialization_conflict_test.dir\main.cpp.obj  /out:template_specialization_conflict_test.exe /implib:template_specialization_conflict_test.lib /pdb:template_specialization_conflict_test.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
  LINK Pass 1: command "C:\PROGRA~2\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\link.exe /nologo CMakeFiles\template_specialization_conflict_test.dir\template_specialization_conflict_test.cpp.obj CMakeFiles\template_specialization_conflict_test.dir\main.cpp.obj /out:template_specialization_conflict_test.exe /implib:template_specialization_conflict_test.lib /pdb:template_specialization_conflict_test.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\template_specialization_conflict_test.dir/intermediate.manifest CMakeFiles\template_specialization_conflict_test.dir/manifest.res" failed (exit code 1169) with the following output:
C:\Users\pc\source\repos\template_specialization_conflict_test\out\build\x64-Debug\main.cpp.obj : error LNK2005: "double __cdecl utils::my_template_function<double>(double)" (??$my_template_function@N@utils@@YANN@Z) already defined in template_specialization_conflict_test.cpp.obj
C:\Users\pc\source\repos\template_specialization_conflict_test\out\build\x64-Debug\template_specialization_conflict_test.exe : fatal error LNK1169: one or more multiply defined symbols found
  ninja: build stopped: subcommand failed.

Rebuild All failed.

我该如何解决这个问题?

【问题讨论】:

  • 不相关:_UTILS_ 是不允许的。它保留给实现使用。
  • 在单个 translation unit(源文件,本质上)中定义特化。
  • template &lt;&gt; double my_template_function&lt;double&gt;(double parameter) 及其整体移动到template_specialization_conflict_test.cpp 源文件中。
  • 关于@ChrisMM 的评论,请阅读What are the rules about using an underscore in a C++ identifier? 它是前导下划线后跟一个大写字母,使其保留。
  • 您是否记得将特化放在源文件的utils 命名空间中?您还记得从头文件中删除特化吗?如果我这样做,我不会出错。

标签: c++ visual-studio templates template-specialization


【解决方案1】:

我该如何解决这个问题?

您可以通过添加/使用关键字inline 来解决这个问题,这样专业化看起来像:

   //note the keyword inline in the below specialization
   template <> inline
    double my_template_function<double>(double parameter)
    {
        std::cout << "function specialization on double";
        std::cout << parameter;
        return parameter;
    }

这可以在here 中看到。

第二种解决此问题的方法是将您的专业化移动到源文件而不是标题中。所以你的 template_specialization_conflict_test.cpp 看起来像: template_specialization_conflict_test.cpp

#include "template_specialization_conflict_test.hpp"

namespace utils
{
    // Template Specialization
    //      A function specialized for double data type
    template <> 
    double my_template_function<double>(double parameter)
    {
        std::cout << "function specialization on double";
        std::cout << parameter;
        return parameter;
    }
}

该程序的工作原理如herehere(with gcc and clang) 所示。

【讨论】:

  • 还有哪些方法?
  • @user366312 我写了“一种方式”,因为我正在考虑其他方式的可能性(如果有的话)。
  • 第二种方式在我的 VS2019 中不起作用。我已经试过了。
  • @user366312 我在 VS 2019 中尝试了第二种方法(都使用 C++ 14 和 17),它编译得很好。不过,您需要在标题中保留专业化的声明。代码似乎并不关心我是否在声明和定义中包含&lt;double&gt;&lt;&gt;
  • @DS_London 绝对需要离开 &lt;&gt; &lt;double&gt; 那里,正如我在问题下的 cmets 中解释的那样。如果可以避免,不要混合使用重载和模板特化。
猜你喜欢
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
  • 1970-01-01
  • 2011-09-22
  • 1970-01-01
相关资源
最近更新 更多