【问题标题】:Lazy type-inference for curried functions柯里化函数的惰性类型推断
【发布时间】:2019-02-06 20:04:47
【问题描述】:

在以下示例中,对mkPair2 的调用的类型推断失败:

#include <functional>

template <class A, class B>
struct Pair {
  A left; B right;
};

template <class A, class B>
Pair<A,B> mkPair1 (A left, B right) {
  return (Pair<A,B>) { left, right };
}

template <class A, class B>
std::function<Pair<A,B>(B)> mkPair2 (A left) {
  return [left] (B right) {
    return (Pair<A,B>) { left, right };
  };
}

Pair<int, char> ex1 = mkPair1 (2, 'a');
Pair<int, char> ex2 = mkPair2 (2) ('a');

问题是mkPair2 有两个模板参数,但是调用(2) 只提供了其中一个,所以编译器立即举手并确定程序是模棱两可的,即使第二种类型可以从以下('a') 调用中推断出来。

这可以通过手动为编译器提供类型mkPair2&lt;int,char&gt; (2) ('a') 来解决,但必须像这样握住编译器的手很快就会变老。

如果每种类型最终都会被解析,是否有任何方法可以诱使编译器继续进行类型检查?

【问题讨论】:

标签: c++ type-inference


【解决方案1】:

即使可以从以下 ('a') 调用中推断出第二种类型。

是的,可以推断,但 C++ 的规则不允许这样做。类型推导只发生在函数参数上。因此,如果模板参数缺少函数参数,则需要自己指定。

也就是说,C++14 的自动返回类型推导和泛型 lambda 将使您不必指定任何内容。您可以将代码重写为

template <class A, class B>
struct Pair {
  A left; B right;
};

template <class A, class B>
auto mkPair1 (A left, B right) {
  return Pair<A,B>{ left, right };
}

template <class A>
auto mkPair2 (A left) {
  return [left] (auto right) {
    return Pair<A, decltype(right)>{ left, right };
  };
}

Pair<int, char> ex1 = mkPair1 (2, 'a');
Pair<int, char> ex2 = mkPair2 (2) ('a');

一切都会为你推导出来。它还返回 lambda 对象,而不是 std::function,因此您可以避免 std::function 使用的类型擦除成本。

【讨论】:

  • +1,也许值得一提的是,在c++17中你可以让编译器从构造函数参数Pair ex1 = mkPair1 (2, 'a')推导出模板参数
  • @AndreasDM 我正在​​考虑这个问题,但可以进一步简化为Pair ex1(2, 'a');。不幸的是,我知道这种情况有一个警告,我需要检查我的参考资料。我也许可以在今晚晚些时候添加。
【解决方案2】:

除了@NathanOliver 的回答之外,您还可以通过自己创建通用 lambda 的等效项来使其适用于 C++11:

template <class A>
struct X {
    A left;
    X(A left) : left(left) {}

    template <class B>
    Pair<A,B> operator()(B right) {
        return Pair<A,B>{left, right};
    }
};

然后:

template <class A>
X<A> mkPair2(A left) {
    return X<A>(left);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-20
    • 2021-06-13
    • 2020-08-18
    • 1970-01-01
    • 1970-01-01
    • 2016-01-01
    • 2018-02-05
    • 1970-01-01
    相关资源
    最近更新 更多