用`std :: function`和先前推导的模板参数替换失败-为什么? [英] Substitution failure with `std::function` and previously deduced template parameter - why?

查看:187
本文介绍了用`std :: function`和先前推导的模板参数替换失败-为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下代码:

template <typename> 
struct S { };

void g(S<int> t);

template <typename T>
void f(T, std::function<void(S<T>)>);

尝试调用时

f(0, g);

我收到以下错误:

error: no matching function for call to 'f'
    f(0, g);
    ^

note: candidate template ignored: could not match 
      'function<void (S<type-parameter-0-0>)>' 
      against 'void (*)(S<int>)'
void f(T, std::function<void(S<T>)>);
     ^

godbolt.org上的实时示例

虽然我了解通常无法推断std::function参数的类型,因为它是非推断的上下文

While I understand that generally the type of the std::function parameter can't be deduced as it is a non-deduced context

在这种情况下,可以先通过传递的参数0推导T,然后将其替换为std::function<void(S<T>)>以获得std::function<void(S<int>)>.

In this case T can first be deduced by the passed argument 0, and then substituted into std::function<void(S<T>)> to get std::function<void(S<int>)>.

我希望推断出T=int之后,编译器将在签名中的所有位置替换T,然后尝试使用参数g构造std::function参数.

I would expect that after deducing T=int, the compiler would substitute T everywhere in the signature and then attempt to construct the std::function parameter with the argument g.

为什么不是这种情况?我假设发生替换/扣除的顺序与此有关,但是我希望看到相关的标准措辞.

Why is that not the case? I presume that the ordering in which substitution/deduction happens has something to do with this, but I'd like to see the relevant Standard wording.

奖金问题:是在将来的标准中可能会在保持向后兼容性的同时进行某些更改吗?还是存在这种替代无效的根本原因?

Bonus question: is this something that could potentially be changed in a future Standard while preserving backwards compatibility, or is there a fundamental reason why this kind of substitution doesn't work?

推荐答案

虽然我了解通常不能推导std :: function参数的类型,因为它是非推论上下文.

While I understand that generally the type of the std::function parameter can't be deduced as it is a non-deduced context.

这不是非推论上下文.恰恰相反.因为尝试对std::function的参数进行推导,但参数为 not std::function,所以推导失败.从函数参数中导出模板参数必须与所有函数参数一致.如果一次失败,那么它将完全失败.

It is not a non-deduced context. Quite the contrary. Because deduction for the parameter of std::function is attempted, but the argument is not a std::function, deduction fails. The deduction of template arguments from function arguments must agree for all function arguments. If it fails for one, it fails entirely.

[温度扣除类型]

2 在某些情况下,使用一组 类型P和A,在其他情况下,将有一组对应的 P和A类型.对每个P/A对分别进行类型推导, 然后将推导的模板参数值组合在一起.如果输入 无法对任何P/A对进行扣除,或者如果对任何P/A对 推导会导致一组以上的推导值,或者 不同的对产生不同的推导值,或者如果有模板 模板既不推论也不明确指定参数 推论失败.

2 In some cases, the deduction is done using a single set of types P and A, in other cases, there will be a set of corresponding types P and A. Type deduction is done independently for each P/A pair, and the deduced template argument values are then combined. If type deduction cannot be done for any P/A pair, or if for any pair the deduction leads to more than one possible set of deduced values, or if different pairs yield different deduced values, or if any template argument remains neither deduced nor explicitly specified, template argument deduction fails.

将第二个函数参数的类型设置为非推导上下文实际上是可以克服该错误的方法.

Making the type of the second function parameter into a non-deduced context is actually how one can overcome the error.

#include <functional>

template<typename T>
struct type_identity {
    using type = T;
};

template <typename> 
struct S { };

void g(S<int> ) {}

template <typename T>
void f(T, typename type_identity<std::function<void(S<T>)>>::type) {}

int main() {
    f(0, g);
}

从第一个函数参数成功推断出

T,没有什么可推论的了.因此,这种追求被认为是成功的.

T is deduced successfully from the first function argument, and there is nothing left to deduce. So the dedcution is deemed a success.

实时

这篇关于用`std :: function`和先前推导的模板参数替换失败-为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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