【问题标题】:let function return template type让函数返回模板类型
【发布时间】:2017-04-07 08:22:34
【问题描述】:

我有以下功能

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());

编辑2

Jonas' answers 第一部分工作只需指定模板类型就足够了:

createObservedEvent<SlabWallConnectionEvent>(pEventData);

但是使用 auto 似乎并不能保证删除返回类型规范:

.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);

仍然给出无法推断类型的第一个错误。

【问题讨论】:

  • link
  • 由于无法从调用位置确定第一个模板参数(它仅用作返回类型),因此您需要在调用函数时明确指定该模板参数。
  • 第二种解决方案的调用将是auto* pEvent = createObservedEvent&lt;ObservedEventType&gt;(pEventData) 而不是createObservedEvent(&amp;pEvent , pEventData);

标签: c++


【解决方案1】:

您必须具体说明返回类型:

createObservedEvent<SlabWallConnectionEvent>(pEventData);

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

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

【讨论】:

  • 使用 auto 并不保证删除返回类型。我已经用我当前的代码更新了我的答案
  • 使用auto,如果编译器可以推断出特定的返回类型,则不需要它。
  • 在我的情况下似乎不能,但我再次承认我有一个相当冒险的设置。我不得不回避不能对成员函数进行模板规范,也不能转发声明内部类。总的来说,我对结果很满意,但这是最后一次改进。
【解决方案2】:

当你有这个时:

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

然后这样称呼它:

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

编译器可以推断出ObservedEventType必须是int并且ObservedEventDataType必须是double,所以它实例化createObservedEvent&lt;int, double&gt;并调用它。

当你改用这个时:

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


您似乎还试图将模板声明放在标题中,并将定义放入 generally doesn't work 的 .cpp 中。

【讨论】:

    猜你喜欢
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-20
    • 2018-04-06
    • 2011-03-04
    • 1970-01-01
    相关资源
    最近更新 更多