【问题标题】:C++ Template method unknown return typeC++模板方法未知返回类型
【发布时间】:2018-09-28 15:52:19
【问题描述】:

我遇到了一段我没有遵循的代码。考虑以下两种方法。

template <typename T>
auto FindElementV1(std::vector<T> elementList, const T& element) {
 return std::find(elementList.begin(), elementList.end(), element);     
}

template <typename T>
auto FindElementV2(std::vector<T> elementList, const T& element) -> typename decltype(elementList)::iterator {
 return std::find(elementList.begin(), elementList.end(), element);     
}

我可以理解FindElementV2 工作,因为该方法的返回类型是使用decltype 指定的。但是为什么FindElementV1 在没有指定返回类型的情况下工作? V1 是符合标准的代码吗?

以下是完整的工作示例。符合 gcc 6.3

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

template <typename T>
auto FindElementV1(std::vector<T> elementList, const T& element) {
 return std::find(elementList.begin(), elementList.end(), element);     
}

int main() {
    std::vector<int> vec = {1,4,2,4,3,5,3,5,3,6};
    auto it = FindElementV1(vec, 5); //< Why does this work without a return type in the method?
    cout<<*it<<endl;
}

【问题讨论】:

    标签: c++ templates iterator c++14 auto


    【解决方案1】:

    [dcl.spec.auto]

    如果函数声明的返回类型包含占位符类型,则函数的返回类型从函数体中的未丢弃的返回语句(如果有)推导出

    还有

    如果具有包含占位符类型的已声明返回类型的函数具有多个未丢弃的返回语句,则为每个此类返回语句推导返回类型。如果每次推导的类型都不相同,则程序是非良构的。

    丢弃的语句是出现在 constexpr if 语句 [stmt.if] 的未采用分支中的语句。

    【讨论】:

    • 您能否详细说明未丢弃的退货声明的含义?换句话说,在什么条件下我必须使用 decltype 指定返回类型。我不能总是使用自动吗?
    • @cplusplusrat 如果您有多个返回不同类型的返回语句,则确实需要指定返回类型。我想一个废弃的return语句是指if constexpr评估为假的分支,但我不知道是否还有其他例子。
    • @cplusplusrat 查看编辑。你真的应该给自己一份标准草案的副本。大多数 PDF 阅读器都有有用的搜索功能。
    • @n.m.你找到我了,我很懒惰。得到了标准的 PDF 草案。
    【解决方案2】:

    C++14 使我们能够编写具有推断返回类型的函数:

    auto foo() { return 5; }
    

    在 C++11 中,这是格式错误的 - 您需要以某种方式指定返回类型。在 C++14 中,我们可以保守地从 return 语句中推断出返回类型。保守地说,我的意思是如果有多个 - 它们都需要是相同的类型,如果你递归,你需要递归第二个而不是第一个。

    扣除遵循正常的模板扣除规则。所以这个:

    auto foo(int& i) { return i; }
    

    返回int,而不是int&amp;

    所有这一切都是说,是的,FindElementV1 是一个完全有效的函数模板......从 C++14 开始。

    【讨论】:

      猜你喜欢
      • 2021-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多