【问题标题】:C++: partial function specialization for void not allowed - alternative solution?C++:不允许 void 的部分函数特化 - 替代解决方案?
【发布时间】:2011-08-11 20:59:54
【问题描述】:

我想我现在明白为什么偏函数模板被认为是令人困惑和不必要的,因此 C++ 标准不允许这样做。但是,我希望能在不使用部分专业化的情况下重新措辞以下功能方面提供一些帮助。 FWIW,该函数是非专业类的成员:

template <typename IMPL, typename RET>
RET call (functor <IMPL> func, 
          IMPL * impl)
{ 
  return func.call (impl);
}

template <typename IMPL>
void call <IMPL, void_t> (functor <IMPL> func, 
                          IMPL * impl) 
{ 
  func.call (impl);
}

这里的问题是我不能重载函数的返回类型。此外,我想专门研究的类型名不用作函数参数 - 重载无济于事的另一个原因。是的,我可以引入一个虚拟参数来强制重载,但这很丑,不是吗?

最后,为什么 C++ 中的类型不是“void”?这会让事情变得更加一致......但我可能错过了完整的画面......

【问题讨论】:

  • void 是 C++ 中的一种类型,而不是数据类型(即您可以拥有 void 函数,但不能拥有 void 数据对象)。相反,如果您认为有必要,您可以尝试使用void*(转换现有数据类型)作为数据
  • 您不需要专门针对voidreturn返回类型为void的函数调用完全没问题。
  • 哇——我怎么能错过那个'return void'的东西呢?似乎我在过去的一段时间里学到了一些错误的东西,它卡住了!非常感谢您提供许多有用的答案,非常有帮助! :-)
  • 再次感谢 - 代码现在看起来更干净了,一切正常,我从你的回答中学到了很多东西 :-)

标签: c++ function templates partial-specialization


【解决方案1】:

我相信,首先,如果你有一个返回 void 的函数,那么 return 一个 void 表达式是完全合法的——例如调用另一个返回 void 的函数,其次,void 是 C++ 中的完整类型,您可以随意将其传递给模板。

【讨论】:

    【解决方案2】:

    首先,

    template <typename IMPL, typename RET>
    RET call (functor <IMPL> func, 
              IMPL * impl)
    { 
      return func.call (impl);
    }
    

    应该是

    template <typename RET, typename IMPL>
    RET call (functor <IMPL> func, 
              IMPL * impl)
    { 
      return func.call (impl);
    }
    

    (我把模板参数列表中的RETIMPL倒置了)这样你就可以像这样调用函数了

    call<int>(f, impl);
    

    无需输入

    call<impl_type, int>(f, impl);
    

    确实,编译器无法推导出RET,所以你必须自己提供。

    其次,您不需要为void 重载,因为可以返回void 表达式。如果你愿意,你可以添加一个重载:

    template <typename IMPL>
    void call(functor<IMPL> func, IMPL* impl)
    

    并在调用此重载时使用call(f, impl)

    如果您可以访问 C++0x,请考虑使用decltype

    【讨论】:

      【解决方案3】:

      如果你的 functor 模板类已经有一个 RET 的 typedef,你可以这样做:

      template <typename IMPL>
      typename functor<IMPL>::RET call (functor <IMPL> func, 
                IMPL * impl)
      { 
        return func.call (impl);
      }
      

      不要为超载而烦恼。另外,您使用的编译器是什么?所有符合标准的编译器都允许您从 void 函数返回 void 函数的结果。

      【讨论】:

      • "VC++ 2010 允许您从 void 函数返回 void 函数的结果。" 所有符合标准的编译器都可以。
      • @ildjarn,是的,嗯……用那个措辞更新。
      【解决方案4】:

      函数部分特化的一般解决方案包括使用具有相同模板参数的辅助类模板,以及具有与函数相同参数的单个方法。然后可以对模板类进行部分特化。

      但是,在您的情况下,我认为您应该能够使用 void 作为您的返回类型,正如其他答案所指出的那样。

      【讨论】:

        【解决方案5】:

        您可以通过使用函数重载来做到这一点:

        template <typename IMPL, typename RET>
        RET call (functor <IMPL> func, 
                  IMPL * impl)
        { 
          return func.call (impl);
        }
        
        template <typename IMPL>
        void call (functor <void_t> func, void_t * impl) 
        { 
          func.call (impl);
        }
        

        另外,void 是 C++ 中的一个类型;是什么让你认为它不是?

        【讨论】:

        • 这可能忽略了仿函数模板参数的含义(显然是传递给call方法的指针类型)。
        猜你喜欢
        • 1970-01-01
        • 2011-08-24
        • 2017-08-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-13
        • 2016-10-24
        • 1970-01-01
        相关资源
        最近更新 更多