为什么我们不能自动推断出退货类型?

时间:2011-09-28 21:26:38

标签: c++ c++11

最近我在找一个想要让C ++更多Haskell-y的朋友,我们想要一个基本上是这样的函数:

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的尾随返回类型的重点是什么?

5 个答案:

答案 0 :(得分:38)

如果我们有以下内容怎么办?

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 + ba + c表达式产生不同类型的结果。 编译器应该将什么作为该函数的返回类型放置?为什么? C ++ 11 lambdas已经涵盖了这种情况,只要return语句可以推导为相同类型,就可以省略返回类型(需要NB标准引用,一些来源声称只允许一个返回表达式,这是一个gcc故障。)


技术原因是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)
{
}

答案 1 :(得分:8)

  

但我们无论如何都不能使用这样的模板。

首先,尾随返回类型不仅仅是模板事物。它们适用于所有功能。其次,说谁?这是完全合法的代码:

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)
{
}

这对许多程序员来说相当普遍。想要以这种方式编码没有任何问题。

lambda在没有返回类型的情况下逃脱的唯一原因是因为它们必须具有使用定义定义的函数体。如果将尾随返回类型限制为仅定义可用的那些函数,则无法使用上述任何一种情况。

答案 2 :(得分:5)

没有技术理由说明为什么不可能。他们没有的主要原因是因为C ++语言的移动非常缓慢,并且需要很长时间才能添加功能。

你可以几乎使用lambdas获得你想要的漂亮语法(但你不能在lambdas中使用templacised参数,再次没有充分的理由)。

auto foo = [](int a, double b)
{
    return a + b;
};

是的,在某些情况下无法自动推断出返回类型。就像在lambda中一样,只需要在那些不明确的情况下自己声明返回类型。

目前,这些限制非常随意,令人非常沮丧。另请参阅删除概念以增加挫败感。

答案 3 :(得分:0)

在Dave Abrahams的blog post中,他讨论了使用此函数语法的提议:

[]min(x, y)
{ return x < y ? x : y }

这是基于多态性lambda的可能提议。他还开始工作here更新clang以支持这种语法。

答案 4 :(得分:-1)

尽管没有技术障碍,但很少希望说服委员会增加这样的语言功能。但也许有可能说服GCC小组添加编译器扩展。