传递给模板函数的两个lambda使参数的类型推导变得模棱两可-为什么? [英] Two lambdas passed to template function makes type deduction of parameter ambiguous -- why?

查看:66
本文介绍了传递给模板函数的两个lambda使参数的类型推导变得模棱两可-为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模板,如果我将其传递给一个lambda,则可以使用,但是在一个相关模板中,该模板需要将两个lambda映射到相同的模板化类型,因此无法推论该类型,并且MSVC ++ Express 2013抱怨template参数不明确.首先要明确的是,这里没有重载(或专业化)操作-下面的两个示例是仅有的带有这些标识符的实体.以下是模板,它们仅将可调用对象应用于参数并返回结果:

I have a template that works if I pass it one lambda, but in a related template that takes two lambdas mapped to the same templated type, it cannot deduce that type, and MSVC++ Express 2013 complains the template parameter is ambiguous. To be clear up front, there is no overloading (or specialization) going on here -- my two examples below are the only entities with those identifiers. Here are the templates, which simply apply the callable objects on an argument and return a result:

    template <class A, class OP>
    auto WhichOp1(A argument, OP firstOp)->decltype(firstOp(argument)) {
        return firstOp(argument);
    }

    template <class A, class OP>
    auto WhichOp2(A argument, OP firstOp, OP secondOp)->decltype(firstOp(argument)) {
        return firstOp(argument) + secondOp(argument);
    }

我可以像这样成功地使用WhereOp1:

I can use WhichOp1 successfully like so:

    int e = WhichOp1(2, [](int i){return i * 2; });

但不会编译类似于WhoOp2的调用:

But a similar call to WhichOp2 won't compile:

    int d = WhichOp2(2, [](int i){return i * 2; }, [](int i){return i * 3; });

我收到以下错误:

错误C2782:'未知类型的chaj :: ops :: WhichOp2(A,OP,OP)':模板参数'OP'不明确

IntelliSense:没有功能模板"chaj :: ops :: WhichOp2"的实例与参数列表匹配 参数类型为:(int,lambda [] int(int i)-> int,lambda [] int(int i)-> int)

IntelliSense: no instance of function template "chaj::ops::WhichOp2" matches the argument list argument types are: (int, lambda []int (int i)->int, lambda []int (int i)->int)

我收集到的是,它根本无法将第一个lambda与第二个lambda结合起来,并不能确定两个OP之间的确切类型.如果我明确实例化,可以很好地解决歧义:

What I gather is that it simply can't take the first lambda with the second one and determine between the two what exactly OP's type should be. If I explicitly instantiate, it works fine to resolve the ambiguity:

    int b = WhichOp2<int, int(*)(int)>(2, [](int i){return i * 2; }, [](int i){return i * 3; });

所以我的问题只是试图更好地了解发生了什么-当在公共模板参数下将两个相似的lambda传递给模板时,为什么编译器无法解决歧义?智能错误似乎将lambda的类型映射到相同的类型.如果这是特定于编译器的,我不会感到惊讶,但是如果有人发现这适用于他们的编译器,我很想知道.

So my question is simply an attempt to have a better understanding of what is going on -- why can the compiler not resolve ambiguity when passing two similar lambdas to a template under a common template parameter? The intellisense error seems to map the type of the lambdas to the same type. I won't be surprised if this is compiler specific, but if anyone sees that this works on their compiler, I'd be interested to know.

推荐答案

C ++标准的5.1.2/3 ([expr.prim.lambda])章说:

The chapter 5.1.2/3 ([expr.prim.lambda]) of C++ standard says:

lambda表达式的类型(也是闭包对象的类型)是唯一的,未命名的ununion类类型

The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed nonunion class type

所以这行中的两个lambdas

So the two lambdas in this line

WhichOp2(2, [](int i){return i * 2; }, [](int i){return i * 3; });

具有不同的类型,即使它们看起来相同.如果要WhichOp2如此工作,则必须使用不同的操作类型对其进行声明:

have different types, even though they look the same. If you want WhichOp2 to work like this you have to declare it with different operation types:

template <class A, class OP1, class OP2>
auto WhichOp2(A argument, OP1 firstOp, OP2 secondOp)->decltype(firstOp(argument) + secondOp(argument)) {
    return firstOp(argument) + secondOp(argument);
}

这篇关于传递给模板函数的两个lambda使参数的类型推导变得模棱两可-为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆