我可以有一个单一的模板与一个变量对象吗? [英] Can I have a single template with a variable object?

查看:122
本文介绍了我可以有一个单一的模板与一个变量对象吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有以下代码:

  template<类Obj,类ObjResult> 
CLStatus convertObjToResult2(const Obj& xFrom,ObjResult& xTo)
{
CLStatus eStatus = CLSTATUS_SUCCESS;
switch(xTo.eType)
{
case CEPTFull:
xTo.xData.xFull = xFrom;
break;
case CEPTBrief:
eStatus = Convert(xFrom,xTo.xData.xBrief);
break;
默认值:
eStatus = CLSTATUS_INVALIDPROJECTIONTYPE;
}
return eStatus;
}

template<类Obj,类ObjResult>
CLStatus convertObjToResult1(const Obj& xFrom,ObjResult& xTo)
{
CLStatus eStatus = CLSTATUS_SUCCESS;
switch(xTo.eType)
{
case CEPTFull:
xTo.xData.xFull = xFrom;
break;
默认值:
eStatus = CLSTATUS_INVALIDPROJECTIONTYPE;
}
return eStatus;
}

所有ObjResults都有 xFull ,但只有一些具有 xBrief ,其中xData是 union 。这导致我写了上面的两个不同的模板,但如果我能以某种方式只有一个模板是很大的。



我不能简单地使用 convertObjToResult2 ,因为它将无法使用没有 xBrief 的对象类型进行编译。我查看了此答案,看看是否会有帮助,但我 c> c>

不会也不会有 a static if

如果你不能重载 Convert 在评论中,我想到了一个层,它可以是专门的,取决于 ObjResult 是否有成员。

  template< class Obj,ObjResult,class = void> 
struct ConvertIfHasBrief {
static auto Convert(Obj const& ObjResult&) - > CLStatus {
return {}; // dymmy value,not used
}
};

template< class Obj,ObjResult类>
struct ConvertIfHasBrief< Obj,ObjResult,
std :: void_t< decltype(std :: declval< ObjResult>()。xData.xBrief)> {
static auto Convert(Obj const& xFrom,ObjResult& xTo){
return :: Convert(xFrom,xTo.xData.xBrief);
}
};



template<类Obj,类ObjResult>
CLStatus convertObjToResult(const Obj& xFrom,ObjResult& xTo)
{
CLStatus eStatus = CLSTATUS_SUCCESS;
switch(xTo.eType)
{
case CEPTFull:
xTo.xData.xFull = xFrom;
break;
case CEPTBrief:
eStatus = ConvertIfHasBrief< Obj,ObjResult> :: Convert(xFrom,xTo);
break;
默认值:
eStatus = CLSTATUS_INVALIDPROJECTIONTYPE;
}
return eStatus;
}

std :: void_t 不是标准的一部分,但实现很简单,可以在链接的页面上找到。只要确保不在 std 命名空间中声明它。



proof it works


I currently have the following code:

template< class Obj, class ObjResult >
CLStatus convertObjToResult2( const Obj & xFrom, ObjResult & xTo )
{
    CLStatus eStatus = CLSTATUS_SUCCESS;
    switch ( xTo.eType )
    {
        case CEPTFull:
            xTo.xData.xFull = xFrom;
            break;
        case CEPTBrief:
            eStatus = Convert( xFrom, xTo.xData.xBrief );
            break;
        default:
            eStatus = CLSTATUS_INVALIDPROJECTIONTYPE;
    }
    return eStatus;
}

template< class Obj, class ObjResult >
CLStatus convertObjToResult1( const Obj & xFrom, ObjResult & xTo )
{
    CLStatus eStatus = CLSTATUS_SUCCESS;
    switch ( xTo.eType )
    {
        case CEPTFull:
            xTo.xData.xFull = xFrom;
            break;
        default:
            eStatus = CLSTATUS_INVALIDPROJECTIONTYPE;
    }
    return eStatus;
}

All ObjResults have an xFull, but only some have an xBrief, where xData is a union. This resulted in me writing the two different templates above, but it would be great if I could somehow have just one template.

I can't simply use convertObjToResult2, since it will fail to compile with object types that do not have an xBrief. I looked at this answer to see if it would help, but I don't understand at all what it's doing.

解决方案

Since C++ does not and won't have a static if feature, you need a work around.

If you can't overload Convert as you said in comments, I thought of a layer above it which can be specialized depending on if ObjResult has the member or not.

template <class Obj, class ObjResult, class = void>
struct ConvertIfHasBrief {
  static auto Convert(Obj const &, ObjResult &) -> CLStatus  {
      return {};// dymmy value, not used
   }
};

template <class Obj, class ObjResult>
struct ConvertIfHasBrief <Obj, ObjResult,
                          std::void_t<decltype(std::declval<ObjResult>().xData.xBrief)>> {
  static auto Convert(Obj const &xFrom, ObjResult &xTo) {
    return ::Convert(xFrom, xTo.xData.xBrief);
  }
};



template< class Obj, class ObjResult>
CLStatus convertObjToResult( const Obj & xFrom, ObjResult & xTo )
{
    CLStatus eStatus = CLSTATUS_SUCCESS;
    switch ( xTo.eType )
    {
        case CEPTFull:
            xTo.xData.xFull = xFrom;
            break;
        case CEPTBrief:
                eStatus = ConvertIfHasBrief<Obj, ObjResult>::Convert(xFrom, xTo);
            break;
        default:
            eStatus = CLSTATUS_INVALIDPROJECTIONTYPE;
    }
    return eStatus;
}

std::void_t is not yet part of the standard, but the implementation is simple and can be found on the linked page. Just be sure not to declare it on the std namespace.

proof it works

这篇关于我可以有一个单一的模板与一个变量对象吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆