【问题标题】:Can template type inference take primitive operation type conversions into account?模板类型推断可以考虑原始操作类型转换吗?
【发布时间】:2018-09-11 09:27:53
【问题描述】:

模板似乎无法对原始操作的结果进行类型推断。例如,以下无法推导出 R:

template<typename A, typename B, typename R>
R addNumbers(A x, B y){
    return x + y;
}
main(){
    addNumbers(1.0f, 1);
}

尽管很明显float + int = float.

在任何版本的 C++ 中,是否有某种方法可以让推理在不明确指定的情况下考虑这些信息?

【问题讨论】:

    标签: c++ c++11 templates c++14 template-meta-programming


    【解决方案1】:

    调用函数时模板参数推导无法查看函数体;它只是试图使函数的参数类型与参数类型相同,并且任何不能以这种方式推导的模板参数都不会被推导。您需要一种基于函数主体中的 return 语句的演绎形式。这是由 C++14 中的auto 提供的:

    template<typename A, typename B>
    auto addNumbers(A x, B y){
        return x + y;
    }
    

    【讨论】:

    • 可选地,如果你想让它非常具体(但恕我直言,不是更易读),你可以使用decltype(x + y)作为返回类型。
    • 这个推演是在编译时进行的吗?
    • @oink 是的
    【解决方案2】:

    decltype 是 C++11 中最好的补充之一。 阅读更多信息:http://en.cppreference.com/w/cpp/language/decltype

    基于 C++11 的解决方案(使用编译器标志 -std=c++11

    template<typename A, typename B>
    auto addNumbers(A const & x, B const & y) -> decltype(x + y)
    {
        return x + y;
    }
    

    decltype最好的部分,你几乎可以在里面写任何表达式,它会在编译时被评估。

    在上面的例子中,我们要求编译器声明函数的返回类型,与表达式 x + y 的返回类型相同,只计算它们的类型。

    基于 C++14 的解决方案(不需要decltype,使用编译器标志-std=c++14

    template<typename A, typename B>
    auto addNumbers(A const & x, B const & y)
    {
        return x + y;
    }
    

    用法:

    auto ans = addNumbers(1.0f, 1); // ans is deduced to be float
    

    【讨论】:

      【解决方案3】:

      函数重载推导,无论是否考虑模板,都没有也不能考虑返回类型。返回类型不是函数签名的一部分。推导只考虑调用的参数是否匹配各种函数声明的参数。以下将匹配任何 A 和 B。如果定义了 operator+ (A, B),则返回类型将是它返回的任何内容。如果operator+ (A, B)没有定义,编译器会报错。

      template<typename A, typename B>
      auto addNumbers(A x, B y){
          return x + y;
      }
      int main(){
          addNumbers(1.0f, 1);
      }
      

      【讨论】:

      • 我觉得这并没有为 1 小时前发布的答案添加任何内容
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多