【问题标题】:auto Function with if Statement won't return a value带有 if 语句的 auto 函数不会返回值
【发布时间】:2017-01-08 18:43:16
【问题描述】:

我制作了一个模板和一个 auto 函数,用于比较 2 个值并返回最小的那个。 这是我的代码:

#include <iostream>
using namespace std;

// Template with a value returning function: PrintSmaller
template <typename T, typename U>
auto PrintSmaller(T NumOne, U NumTwo) {
    if (NumOne > NumTwo) {
        return NumTwo;
    }
    else {
        return NumOne;
    }
}

int main() {

    int iA = 345;
    float fB = 23.4243;

    cout << PrintSmaller(iA, fB) << endl;
    cout << PrintSmaller(fB, iA) << endl;

    return 0;
}

但它不会编译,我在 VS 2015 上收到此错误: 错误 C3487 'int':所有返回表达式必须推导出为相同的类型:以前是 'float'

但是,如果我删除 if 语句并像这样编写函数 PrintSmaller问题:

auto PrintSmaller(T NumOne, U NumTwo) {
return (NumOne < NumTwo ? NumOne : NumTwo);
}

有什么区别?为什么第一个代码无法编译? 谢谢。

【问题讨论】:

  • 三元语句可能会导致隐式转换。 This 可能是相关的。
  • 你是用 -std=c++11 还是 -std=c++14 编译?

标签: c++


【解决方案1】:

一个函数只能有一个return 类型。使用return 类型推导意味着它将根据解析器看到的first return 语句中表达式的类型进行推导。如果后面的return 语句不返回相同类型的表达式,则该函数被认为是自相矛盾的,因此格式错误。

在第二种情况下,?: 根据第二个和第三个子表达式确定的公共类型确定表达式的类型。这两个子表达式将被转换为这种通用类型。

这与return 类型推导的工作方式不同。如果您打算让您的第一个案例工作,那么您需要显式将返回的值转换为所需的返回类型。

【讨论】:

    【解决方案2】:

    当您使用 c++11 标记提出这个问题时,我想您使用的是 C++11。不幸的是,C++11 标准规定自动类型推导(也适用于 lambda)仅限于单个语句。

    由于?: 运算符是表达式而不是语句,所以当if-else 是语句并且不满足要求时,这将起作用。

    如果您使用 C++14 标准编译此代码,您将看到它应该编译这两种情况,因为此限制已删除。

    【讨论】:

    • 对不起,我实际上正在开发 VS 2015,我认为它使用最新的标准 c++14
    【解决方案3】:

    直到昨天(2017-12-06),这还没有在 MSVC 下编译。但在 VS 15.5 更新后它确实如此。

        auto msvc_does_compile = [](auto _string)
         {
          using string_type = decltype(_string);
          return std::vector<string_type>{};
         };
       /*
        OK since VS 2017 15.5 update
       auto vec1 = msvc_does_compile( std::string{} );
       */
    

    添加显式返回类型会阻塞 MSVC,但不会像往常一样阻塞 gcc/clang:

    auto msvc_does_not_compile = [](auto _string)
        // explicit return type makes msvc not to compile
        -> std::vector< decltype(_string) >
      {
        using string_type = decltype(_string);
        return std::vector<string_type>{};
      };
    

    即使在 IDE 阶段也会停止一些相同但更简单的事情:

        auto msvc_ide_does_not_allow = []( bool wide )
        {
           if (wide)
            return std::vector<std::string>();
    
            return std::vector<std::wstring>();
        };
    

    是的,同样麻烦的 gcc/clang 对在上面没有问题。尝试使用哪种在线 ide 来说服自己...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-07
      • 1970-01-01
      相关资源
      最近更新 更多