【问题标题】:Function template overloading (different return value type)函数模板重载(不同的返回值类型)
【发布时间】:2014-07-27 07:38:49
【问题描述】:

我在看C++ Templates: The Complete Guide,在《13.7 Partial Specialization of Function Templates》作者说:

要重载函数模板,它们的函数参数必须在某些实质性方面有所不同。考虑一个函数模板 R convert(T const&) 其中 R 和 T 是模板参数。我们可能很想为 R = void 专门化这个模板,但这不能使用重载来完成。

可以使用函数模板重载来完成,对吧?如:

#include <iostream>

template <typename T, typename R>
R convert(T const&) { std:: cout << "R convert(T const&)\n"; }
template <typename T>
void convert(T const&) { std:: cout << "void convert(T const&)\n"; }

int main()
{
    convert(0);
}

DEMO 这里,结果是:

void 转换(T const&)

作者的真正意思是什么?

【问题讨论】:

  • 作者可能指的是C++缺乏对返回类型重载的支持。
  • @nix 但是函数模板重载支持。
  • 我认为您遇到了一些 UB,您的编译器不够聪明,无法发出警告。尝试在第一个 convert 中添加一个 return 语句(这样它就可以用 int i=convert(0) 编译), then replace the call to convert(0)`。它不会编译。
  • 编译器无法为第一个模板推导出R,所以它永远不会被选中。
  • @nix 因为作者在谈论“部分专业化”和“重载”之间的区别,但我认为这也不能通过专业化来完成。所以我无法从书中得到上述上下文的意义。

标签: c++ templates


【解决方案1】:

考虑一个类模板的偏特化:

template<class U, class V> class T { };

template<class V> class T<void, V> { };

当你写T&lt;void, int&gt;时,将使用部分特化。

现在考虑一个函数模板:

template <typename R, typename T>
R convert(T const&) { return /* something */; } 

请注意,RT 的顺序在上面的模板参数列表中互换。这可能就是这样一个模板的编写方式——您编写convert&lt;R&gt;(something),明确指定目标类型,同时让编译器推断源类型。

现在假设您希望convert&lt;void&gt;(something) 做一些不同的事情。你不能用重载来做到这一点:

template <typename T>
void convert(T const&) { } 

如果您编写 convert(something) - 以前格式不正确,它将转到您的新重载,因为编译器无法为第一个模板推导出 R。但如果你写convert&lt;void&gt;(something) 甚至convert&lt;void, T&gt;(something),它仍然会转到原始模板。更糟糕的是,像 convert&lt;int&gt;(1) 这样的东西现在格式不正确,因为它是模棱两可的。

换句话说,您不能让convert&lt;void, T&gt;(something) 使用与convert&lt;int, T&gt;(something) 不同的实现,而您可以使用类模板部分特化来做到这一点。

【讨论】:

  • 我认为作者是在暗示功能模板的部分专业化可以做到这一点......我的误解?
  • @songyuanyao C++ 中没有函数模板偏特化之类的东西。作者似乎在讨论一些可以通过对标准进行假设修改以允许函数模板部分特化来解决的情况,但标准从未以这种方式改变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 2019-12-18
  • 1970-01-01
相关资源
最近更新 更多