最近我和一个 friend 一起工作,他想让 C++ 更像 Haskell,我们想要一个基本上像这样的函数:
auto sum(auto a, auto b) {
return a + b;
}
显然我不能使用auto作为参数类型,所以我改成这样:
template<class A, class B>
auto sum(A a, B b) {
return a + b;
}
但这也不起作用。我们最终意识到我们需要这个:
template<class A, class B>
auto sum(A a, B b) -> decltype(a + b) {
return a + b;
}
所以我的问题是,有什么意义?不是decltype
只是重复信息,因为编译器可以只看return语句吗?
我认为可能需要它,所以我们可以只包含一个头文件:
template<class A, class B>
auto sum(A a, B b) -> decltype(a + b);
...但无论如何我们都不能使用这样的模板。
我考虑的另一件事是编译器可能更容易,但似乎实际上会更难。
案例1:使用decltype
- 找出
decltype
语句的类型 - 找出任何返回值的类型
- 看看他们是否匹配
案例2:没有decltype
- 找出任何返回值的类型
- 看看他们是否匹配
考虑到这些,decltype
的尾随返回类型有什么意义?
最佳答案
好吧 - 自从提出原始问题以来已经过去了一段时间,现在的答案是你可以!
是的,这个问题确实被标记为 C++11 - 你仍然不能按照 OP 的要求去做。但值得展示 C++14 及更高版本的功能。
自 C++14 起这是有效的:
template<class A, class B>
auto sum(A a, B b) {
return a + b;
}
从 C++20 开始,这也是有效的:
auto sum(auto a, auto b) {
return a + b;
}
以下是C++11 的答案,出于历史原因保留在这里,还有一些来自 future 的评论(C++14 及更高版本):: p>
如果我们有以下情况:
template<class A, class B, class C>
auto sum(A a, B b, C c) {
if (rand () == 0) return a + b;
// do something else...
return a + c;
}
.. 其中 a + b
和 a + c
表达式产生不同类型的结果。
编译器应该决定将什么作为该函数的返回类型,为什么?
这种情况已经被 C++11 lambdas 覆盖,只要 return
语句可以推导出为相同的类型,就可以省略返回类型(需要注意标准引用,一些来源声称只有一个返回表达式是允许的,这是 gcc 故障)。
来自 future 的注释(C++14 及更高版本):上面的示例仍然无效,您可能只有一个可能的返回类型。但是,如果有不同的返回类型,但实际的返回类型可以在编译类型时推断出来,那么我们有两个不同的函数,这是有效的。以下示例自 C++17 起有效:
template<class A, class B, class C>
auto sum(A a, B b, C c) {
if constexpr(std::is_same_v<A, B>) return a + b;
else return a + c;
}
int main() {
auto a1 = sum(1, 2l, 3.5); // 4.5
auto a2 = sum(1, 2, 3.5); // 3
}
回到原来的C++11答案,解释为什么不支持请求的语法:
一个技术原因是 C++ 允许定义和声明是分开的。
template<class A, class B>
auto sum(A a, B b) -> decltype(a + b);
template<class A, class B>
auto sum(A a, B b) -> decltype(a + b)
{
}
模板的定义可以在标题中。或者它可以在另一个文件中,这样您在查看界面时就不必费力地翻阅一页又一页的函数定义。
C++ 必须考虑所有可能性。将尾随返回类型限制为仅函数定义意味着您不能做这么简单的事情:
template<class A, class B>
class Foo
{
auto sum(A a, B b) -> decltype(a + b);
}
template<class A, class B>
auto Foo<A, B>::sum(A a, B b) -> decltype(a + b)
{
}
来自 future 的注释(C++14 及更高版本):如果在编译器看到调用时定义不可用,您仍然不能拥有具有 auto
返回类型的声明.
关于c++ - 为什么我们不能自动推断返回类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7589809/