使用开关自动返回功能值

时间:2018-11-26 15:47:39

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

我正在尝试创建一个函数,其返回类型应取决于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'

如何通过功能来创建与上面的示例类似的内容?

3 个答案:

答案 0 :(得分:13)

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

将让您返回不同的类型。

答案 1 :(得分:6)

如果在编译时知道函数参数,则可以使用编译时分配,例如

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-类型如现有答案所示。

请注意,正如@NathanOliver在评论中指出的那样,还有一个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; }

此模板的使用及其专业化与上面的内容没有什么不同。

答案 2 :(得分:2)

错误消息说明了一切:函数的所有分支必须返回相同的类型。此限制并不特定于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