我试图向我的类添加一个新的模板助手函数,现在我得到了一个LNK2001错误.如何修复



我最近在StackOverflow上问了几个问题,看看是否可以通过使用模板将一些函数合并为一个函数。这些问题是:

  1. 这些将安全数组转换为std::list对象的方法可以转换为模板函数吗
  2. 此模板函数是否可以适用于以下方法

我还有一个功能要尝试和更新,所以我想我会自己尝试一下。

这是要更新的功能:

void CMSATools::ConvertSAFEARRAY_DATE(SAFEARRAY* psaDates, MeetingDates& rMapMeetingDates)
{
DATE *pVals = nullptr;
HRESULT hr = SafeArrayAccessData(psaDates, (void**)&pVals); // direct access to SA memory
if (SUCCEEDED(hr))
{
long lowerBound, upperBound;  // get array bounds
hr = SafeArrayGetLBound(psaDates, 1, &lowerBound);
if (FAILED(hr))
throw _com_error(hr);
hr = SafeArrayGetUBound(psaDates, 1, &upperBound);
if (FAILED(hr))
throw _com_error(hr);
long cnt_elements = upperBound - lowerBound + 1;
for (int i = 0; i < cnt_elements; ++i)  // iterate through returned values
{
COleDateTime datNotAvailable(pVals[i]);
DWORD dwDatNotAvailable = EncodeMeetingDate(0, datNotAvailable);
rMapMeetingDates[dwDatNotAvailable] = datNotAvailable;
}
hr = SafeArrayUnaccessData(psaDates);
if (FAILED(hr))
throw _com_error(hr);
}
else
{
throw _com_error(hr);
}
hr = SafeArrayDestroy(psaDates);
if (FAILED(hr))
throw _com_error(hr);
}

MeetingDates的定义如下:

using MeetingDates = std::map<DWORD, COleDateTime>;

所以我创建了这个助手函数:

template<>
void CMSATools::to_push_back(const DATE& rItem, MeetingDates& rItems)
{
COleDateTime datNotAvailable(rItem);
DWORD dwDatNotAvailable = EncodeMeetingDate(0, datNotAvailable);
rItems[dwDatNotAvailable] = datNotAvailable;
}

我调整了我的呼叫代码如下:

theApp.MSAToolsInterface().ConvertSAFEARRAY<DATE,MeetingDates>(psaDates, mapMeetingDates);

但当我编译这个时,我现在得到了一个错误:

5>PublishersDatabaseDlg.obj:错误LNK2001:未解析的外部符号";public:static void __cdecl CMSATools::ConvertSAFEARRAY<double,类std::map<unsigned long,类ATL::COleDateTime,结构std::less,类std::分配器<structstd::对<无符号长常量,类ATL::COleDateTime>gt>gt;(结构体tagSAFEARRAY*,类std::map<unsigned long,类ATL::COleDateTime,结构体std::less,类std::分配器<结构体std::对<无符号long const,类ATL::COleDateTime>>("($ConvertSAFEARRAY@NV$map@KVCOleDateTime@ATL@@U$less@K@std@@V$allocator@U$成对@$$CBKVCOleDateTime@ATL@@@std@@@4@@std@@CMSATools@@SAXPAUtagSAFEARRAY@@AAV$map@KVCOleDateTime@ATL@@U$less@K@std@@V$allocator@U$成对@$$CBKVCOleDateTime@ATL@@@std@@@4@@std@@@Z(

我做错了什么?


到目前为止,当我制作DATE时,我的代码不会编译。。。模板调用:

template<typename to>
void CMSATools::to_clear(to& rItems)
{
rItems.clear();
}
template<typename from, typename to>
void CMSATools::to_push_back(const from& rItem, to& rItems)
{
rItems.push_back(rItem);
}
template<>
void CMSATools::to_clear(CStringArray& rItems)
{
rItems.RemoveAll();
}
template<>
void CMSATools::to_push_back(const BSTR& rItem, CStringArray& rItems)
{
rItems.Add(rItem);
}
template<>
void CMSATools::to_push_back(const DATE& rItem, MeetingDates& rItems)
{
COleDateTime datNotAvailable(rItem);
DWORD dwDatNotAvailable = EncodeMeetingDate(0, datNotAvailable);
rItems[dwDatNotAvailable] = datNotAvailable;
}
template<typename from, typename to>
void CMSATools::ConvertSAFEARRAY(SAFEARRAY* psaItems, to& rItems)
{
from* pVals = nullptr;
HRESULT hr = SafeArrayAccessData(psaItems, (void**)&pVals); // direct access to SA memory
if (SUCCEEDED(hr))
{
long lowerBound, upperBound;  // get array bounds
hr = SafeArrayGetLBound(psaItems, 1, &lowerBound);
if (FAILED(hr))
throw _com_error(hr);
hr = SafeArrayGetUBound(psaItems, 1, &upperBound);
if (FAILED(hr))
throw _com_error(hr);
to_clear<to>(rItems);
long cnt_elements = upperBound - lowerBound + 1;
for (int i = 0; i < cnt_elements; ++i)  // iterate through returned values
{
to_push_back<from, to>(pVals[i], rItems);
}
hr = SafeArrayUnaccessData(psaItems);
if (FAILED(hr))
throw _com_error(hr);
}
else
{
throw _com_error(hr);
}
hr = SafeArrayDestroy(psaItems);
if (FAILED(hr))
throw _com_error(hr);
}

这是对类似标题问题的回答:

将std::map作为模板模板参数传递时出错

我认为这可能适用于我的情况,但我不确定如何实施。如果真的是原因的话。


我的头类中有以下代码段:


template<typename to>
static void to_clear(to& rItems);
template<typename from, typename to>
static void to_push_back(const from& rItem, to& rItems);
template<>
static void to_clear(CStringArray& rItems);
template<>
static void to_push_back(const BSTR& rItem, CStringArray& rItems);
template<>
static void to_push_back(const DATE& rItem, MeetingDates& rItems);
template<typename from, typename to>
static void ConvertSAFEARRAY(SAFEARRAY* psaItems, to& rItems);
static DWORD EncodeMeetingDate(int iMeetingType, COleDateTime datMeeting);

在我的头文件的顶部,我有:

#pragma once
#include "DemoPickerDlg.h"
#include <map>
#include <vector>
#ifdef _WIN64
#import "..\..\MSAToolsLibrary\MSAToolsLibrary\bin\x64\Release\MSAToolsLibrary.tlb" raw_interfaces_only named_guids
#else
#import "..\..\MSAToolsLibrary\MSAToolsLibrary\bin\x86\Release\MSAToolsLibrary.tlb" raw_interfaces_only named_guids
#endif
using MeetingDates = std::map<DWORD, COleDateTime>;
using ListDiscussionItems = std::list<MSAToolsLibrary::IDiscussionItemPtr>;
using ListStudentItems = std::list<MSAToolsLibrary::IStudentItemPtr>;
using ListDutyHistoryLookupItems = std::list<MSAToolsLibrary::IDutyAssignmentLookupPtr>;

在评论中向我提供了一个链接问题(为什么模板只能在头文件中实现?(。但答案本身并没有让我明白。正是它链接到的文章帮助我理解了:

  • 为什么我不能将模板类的定义与其声明分离,并将其放入.cpp文件中

引用:

但为了理解为什么事情是这样的,首先要接受以下事实:

  1. 模板不是类或函数。模板是编译器用来生成一系列类或函数的"模式">

这让我明白了。我把模式代码移到了头中,现在它编译得很好。我发现这是最简单的解决方案。

最新更新