【发布时间】:2020-12-05 08:43:41
【问题描述】:
考虑一下:
template<typename T>
struct base_t
{
auto& f(int x) { return (T&)*this; }
auto& f(char x) { return (T&)*this; }
};
struct derived_t : base_t<derived_t>
{
};
void test()
{
derived_t instance;
auto lambda = [&](derived_t&(derived_t::*g)(char))
{
(instance.*g)('a');
//instance.f('a');
};
lambda(&derived_t::f);
}
如果不在该特定行 (//instance.f('a');) 中进行评论,我会收到以下错误 (MSVC 2019):
error C2664: 'void test::<lambda_1>::operator ()(derived_t &(__cdecl derived_t::* )(char)) const': cannot convert argument 1 from 'overloaded-function' to 'derived_t &(__cdecl derived_t::* )(char)'
当该行没有被注释掉时,它编译得很好。
为什么在lambda 中引用f 会神奇地允许编译器转换这个重载函数?
此外,没有 CRTP,这根本不会发生。
编辑:此外,正如@Jarod42 所指出的,
-
明确返回类型 auto& -> T& 解决了这个问题。
-
如果您使用命名函数而不是 lambda,问题就会消失。所以显然 lambda 和模板的交互是相关的。
【问题讨论】:
标签: c++ lambda c++17 overloading crtp