【问题标题】:C++ Function Template With Flexible Return Type具有灵活返回类型的 C++ 函数模板
【发布时间】:2010-12-25 16:19:08
【问题描述】:

假设我们有一个这样的函数

template <class T, class T2>
T getMin(T a, T2 b) {
  if(a < b)
    return a;
  return b;
}

如果我们这样调用函数

int a, b;
long c;

a = getMin(b, c);

如果 c 是

是否可以使返回类型灵活,使其返回 int、long 或任何其他被 "

编辑: 函数中涉及的类型可以是从简单类型到有时无法进行类型转换的复杂类的任何类型。

【问题讨论】:

  • @Prasoon:我希望你取消删除你的答案,因为它是正确的。即使(a &gt; b)? a: b 不能在编译时求值,它仍然有一个类型。使用auto x = (a &gt; b)? a: b; 声明局部变量是有效的,因此使用decltype 也是如此。

标签: c++ templates


【解决方案1】:

C++0x 将允许您使用 auto 关键字,以便让编译器导出表达式的返回时间。


对于 C++03,我发现使此类过程自动化的唯一方法是定义一个模板类 Promotion,它定义了两种类型之间的最强类型,然后将其专门用于您可能需要使用的任何几种类型。

template<> class Promotion< long, int > { typedef long strongest; }
template<> class Promotion< int, long > { typedef long strongest; }

因此:

template< typename T1, typename T2 >
Promotion<T1,T2>::strongest function( const T1 &a, const T2 &b ) { ... }

如果您选择尝试此解决方案,我建议使用自动生成的头文件生成促销专业化。


编辑:我在阅读了另一个(现已删除)答案后重新阅读了这个问题:

您不能返回较小变量的类型。那是因为变量的值只会在运行时被发现,而你的函数返回类型必须在编译时定义。

我提出的解决方案将始终返回两个变量类型之间最强的类型。

【讨论】:

  • 不,但是 decltype 可以很容易地找到更强的类型。例如,getMin(T a, T2 b) -&gt; decltype(a | b)。那么就不需要手动编写数以万计的专业化了。
  • 确实如此,但auto + decltype 不是 C++03 标准。
  • 这可以工作,但只有当方程中涉及的类型是简单类型时。通过返回两者之间最强的类型,我们避免了精度损失,但我们仍然没有得到实际的类型。
  • 正如我在编辑中添加的那样,函数不能返回运行时选择的类型。该函数必须在编译时静态定义其返回类型。如果您必须获得无法使用函数的实际类型,则可以使用宏来代替。另一种解决方案可能是返回两个值,一个T 和一个T2 对象(例如:在一个元组中)加上另一个值来指定哪个是正确的。
【解决方案2】:

如前所述,您希望采用更通用的类型。比如,intdouble 应该变成 doublechar*string 应该变成 string。这适用于我的 promote&lt;&gt; 模板。随便写

template <class T1, class T2>
typename promote<T1, T2>::type getMin(T1 const& a, T2 const& b) {
  if(a < b)
    return a;
  return b;
}

这将始终返回一个副本,即使 T1T2 是相同类型(如 string),这就是为什么我会为非 const 相同类型参数重载它

template <class T>
T &getMin(T &a, T &b) {
  if(a < b)
    return a;
  return b;
}

这两个变体似乎是一个合理的配置。如果您想要一个风险稍大但在更多情况下性能更高的解决方案,您可以接受T const&amp;,也接受临时的。如果你然后像getMin(a + b, b + c) 那样使用它,它可以传递临时变量,并直接使用结果,那很好。结果是可用的,并且仍然可以复制到局部变量中。

【讨论】:

  • 这可以在任何地方编译吗?毕竟,Andrei 抱怨当前的编译器没有接受该解决方案——但不可否认,那是几年前的事了。
  • @Konrad 不知道他的解决方案是什么。但据我记得,他试图用“getMin”左值返回版本来捕捉更多案例。
  • 我的意思是这个开创性的工作:drdobbs.com/184403774 ......我刚刚意识到它是从 2001 年开始的,所以相关段落(“有一些细节值得一提。遗憾的是,Min 不适用于我的任何编译器可以访问。公平地说,每个编译器都会阻塞不同的代码段。”)可能已经过时了。
猜你喜欢
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 2019-04-18
  • 1970-01-01
  • 2015-07-20
  • 2018-04-06
  • 1970-01-01
相关资源
最近更新 更多