【问题标题】:Auto function returning value using switch使用开关的自动功能返回值
【发布时间】:2018-11-26 15:47:39
【问题描述】:

我正在尝试创建一个返回类型应取决于 switch 语句的函数,例如:

auto function_name (int value) {
    switch (value) {
        case 1 : {return 2.3;}
        case 2 : {return 1;}
        case 3 : {return "string";}
    }
}

但我不能因为一个错误:

error: inconsistent deduction for auto return type: 'double' and then 'int'

我可以做些什么来创建类似于上面示例的功能?

【问题讨论】:

  • 由于多种原因,您不能这样做。 auto 必须在编译时知道。
  • C++ 是一种静态类型语言。
  • 您可能对std::variant感兴趣。
  • 你想用这个解决什么实际问题?这根本不是类型在 C++ 中的工作方式。虽然您可以使用 std::variant,但我不太愿意推荐它。

标签: c++ return-type auto type-deduction


【解决方案1】:

C++ 中的函数只能有一个返回的类型。如果您使用auto 作为返回类型,并且您有不同的返回语句返回不同的类型,那么代码格式错误,因为它违反了单一类型规则。

这里需要使用std::variantstd::any。如果您有几种不同的类型可以通过一些运行时值返回,那么您可以将这些类型中的任何一种用作“通用类型”。 std::variant 更严格,因为您必须指定它可能的类型,但它也比 std::any 便宜,因为您知道它可能是什么类型。

std::variant<double, int, std::string> function_name (int value) {
    using namespace std::literals::string_literals;
    switch (value) {
        case 1 : {return 2.3;}
        case 2 : {return 1;}
        case 3 : {return "string"s;} // use ""s here to force it to be a std::string
    }
}

会让你返回不同的类型。

【讨论】:

  • std::variant&lt;auto&gt; 不过会很不错。
  • @BartekBanachewicz 它是否收集了返回语句使用的所有类型?那会很酷。
  • 届时将不得不将 "string" 更改为 "string"s
  • IMO 这个答案应该提到这可能/很可能是错误的方式。 variant 在特定情况下是正确的工具,但它很容易成为设计缺陷的指标。是的,我知道,您无法从问题中准确判断,但我觉得值得一提。否则,提问者可能会试图从中途恢复(或完全恢复,any)离开导致更多滥用的类型系统。
  • @Jarod42 这也困扰着我。你来的时候我正在编辑。
【解决方案2】:

如果函数参数在编译时已知,您可以使用编译时调度,例如

template <int N>
constexpr auto function_name()
{
   if constexpr(N == 1)
      return 2.3;
   else if constexpr (N == 2)
      return 1;
   else
      return "string";
}

可以如下实例化和调用

std::cout << function_name<1>() << "\n";

if constexpr 部分需要 C++17。请注意,将返回值绑定到变量时,请仔细选择类型(例如,不要意外地将double 隐式转换为int),使用类型推导或variant-type,如现有答案所示.

请注意,正如@NathanOliver 在 cmets 中指出的那样,还有一个 pre-C++17 解决方案使用模板专业化而不是 if constexpr

template <int N> constexpr auto function_name() { return "string"; }
template <> constexpr auto function_name<1>() { return 2.3; }
template <> constexpr auto function_name<2>() { return 1; }

这个模板的用法和它的特化与上面没有区别。

【讨论】:

    【解决方案3】:

    错误信息说明了一切:函数的所有分支必须返回相同的类型。此限制并非特定于 auto 返回类型。

    一种可能的解决方法:

    std::variant<double, int, std::string> function_name(int value) {
        switch(value) {
        case 1 : return 2.3;
        case 2 : return 1;
        case 3 : return "string";
        default: throw;
        }
    }
    

    或者,您可以使用boost::variant

    【讨论】:

    猜你喜欢
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    • 1970-01-01
    • 2012-02-12
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多