2017-04-07 125 views
1

我有以下功能让函数返回模板类型

SlabWallConnectionEvent* createObservedEvent(SlabWallConnectionEvent::Data* pEventData) 
{ 
    assert(pEventData != nullptr); 
    return SlabWallConnectionEvent::create(pEventData->m_wall, pEventData->m_slab); 
} 

然后我就能够做出更一般的模板,从它与模板规范。

.h文件中

template <class ObservedEventType, class ObservedEventDataType> 
void createObservedEvent(ObservedEventType*& pEvent,ObservedEventDataType* pEventData); 

.cpp文件

template<> 
void createObservedEvent<SlabWallConnectionEvent, SlabWallConnectionEvent::Data> 
       (SlabWallConnectionEvent*& pEvent, SlabWallConnectionEvent::Data* pEventData) 
{ 
    assert(pEventData != nullptr); 
    pEvent = SlabWallConnectionEvent::create(pEventData->m_wall, pEventData->m_slab); 
} 

这完全适用于我,但我不是太高兴,参考原始指针。是否有可能改变它的东西是这样的:

.h文件中

template <class ObservedEventType, class ObservedEventDataType> 
ObservedEventType* createObservedEvent(ObservedEventDataType* pEventData); 

.cpp文件

template<> 
SlabWallConnectionEvent* createObservedEvent<SlabWallConnectionEvent, SlabWallConnectionEvent::Data> 
       (bim_ui::SlabWallConnectionEvent::Data* pEventData) 
{ 
    assert(pEventData != nullptr); 
    return bim_ui::SlabWallConnectionEvent::create(pEventData->m_wall, pEventData->m_slab); 
} 

当我尝试使用此我得到以下错误:

Error 1 error C2783: 'ObservedEventType 
*createObservedEvent(ObservedEventDataType *)' : could not deduce template 
argument for 'ObservedEventType' 

编辑
我在一个模板函数

template <class ObservedEventType> 
void CmdBimDrag::observeConnectionEvent(ObservedEventData* pObservedEvent){ 
    ... 
    if (pCurrentEvent == nullptr) 
     createObservedEvent(pCurrentEvent, pEventData); 
    ... 
} 

使用此功能,该功能被称为像这样

observeConnectionEvent<SlabWallConnectionEvent>((*pObservedEventData).get()); 

EDIT2

Jonas' answers第一部分工作只是指定的模板类型是不够的:

createObservedEvent<SlabWallConnectionEvent>(pEventData); 

但是使用自动似乎并不保证除去返回类型spefication的:

.h文件中

template <class ObservedEventType, class ObservedEventDataType> 
auto createObservedEvent(ObservedEventDataType* pEventData) -> ObservedEventType*; 

.cpp文件

template<> 
auto createObservedEvent<SlabWallConnectionEvent, SlabWallConnectionEvent::Data> 
    (SlabWallConnectionEvent::Data* pEventData) -> SlabWallConnectionEvent* 
{ 
    assert(pEventData != nullptr); 
    return SlabWallConnectionEvent::create(pEventData->m_wall, pEventData->m_slab); 
} 

此代码与模板规范,但只是编译打电话:

createObservedEvent(pEventData); 

还给出了第一个错误能够推断出类型。

+0

请参见[link](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file?rq=1) – Jay

+0

由于第一个模板参数不能从调用位置确定(它仅用作返回类型),您需要在调用函数时明确指定该模板参数。 –

+0

第二种解决方案的调用是'auto * pEvent = createObservedEvent (pEventData)'而不是'createObservedEvent(&pEvent,pEventData);'。 – Jarod42

回答

2

你必须要具体说明的返回类型:

createObservedEvent<SlabWallConnectionEvent>(pEventData); 

这里是一个example,使用简单的类型。

或者,您可以使用auto作为返回类型,并且不包含返回类型的模板参数。在线示例here

+0

使用auto不保证删除返回类型。 我用我现在的代码更新了我的答案 – turoni

+0

使用'auto',如果编译器可以推导出它,则不需要特定的返回类型。 – Jonas

+0

似乎它不能在我的情况下,但我再次承认我有一个相当危险的设置。我不得不避开成员函数的模板规范,不能转发声明的内部类。总的来说,我对结果很满意,但这是最后一次改进。 – turoni

2

当你有这样的:

template <class ObservedEventType, class ObservedEventDataType> 
void createObservedEvent(ObservedEventType*& pEvent,ObservedEventDataType* pEventData); 

,并调用它像这样:

int *ip; 
double *dp; 
createObservedEvent(ip, dp); 

编译器可以推断ObservedEventType必须intObservedEventDataType必须double,所以它实例createObservedEvent<int, double>和电话它。

当你使用这个来代替:

template <class ObservedEventType, class ObservedEventDataType> 
ObservedEventType* createObservedEvent(ObservedEventDataType* pEventData); 

,并调用它像

double *dp; 
int *ip = createObservedEvent(dp); 

编译器可以推断ObservedEventDataType必须是double,但它不能推断ObservedEventType应该是什么(因为函数的返回类型和变量的类型不需要完全匹配,也不用于扣除)。

为了解决这个问题,你可以手动告诉编译器应该是这样的东西ObservedEventType

double *dp; 
int *ip = createObservedEvent<int>(dp); 

现在知道的第一个模板参数ObservedEventTypeint,因为你说的话,和ObservedEventDataType被推断为double


你似乎也试图把声明为你的模板页眉和定义到的.cpp这generally doesn't work