C++ 17的类模板的"模板参数推导"可以推导出本地类型吗?

Vit*_*meo 8 c++ gcc templates template-argument-deduction c++17

P0091R3 ("类模板的模板参数推导")最近添加到gcc主干,可以在wandbox上进行测试.

我想到的是在很少的代码行中用它来实现"范围保护"的可能性 :

scope_guard _([]{ cout << "hi!\n" });
Run Code Online (Sandbox Code Playgroud)

我尝试在wandbox上实现它 ...

template <typename TF>
struct scope_guard : TF
{
    scope_guard(TF f) : TF{f} { }
    ~scope_guard() { (*this)(); }
};

int main() 
{
    scope_guard _{[]{}};
}
Run Code Online (Sandbox Code Playgroud)

...但编译失败,出现以下错误:

prog.cc:6:5: error: 'scope_guard(TF)-> scope_guard<TF> [with TF = main()::<lambda()>]', declared using local type 'main()::<lambda()>', is used but never defined [-fpermissive]
     scope_guard(TF f) : TF{std::move(f)} { }
     ^~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)

然后我尝试使用非lambda本地类型,并得到相同的错误.

int main() 
{
    struct K { void operator()() {} };
    scope_guard _{K{}};
}
Run Code Online (Sandbox Code Playgroud)

之后,我尝试了非本地类型,它按预期工作.

struct K { void operator()() {} };

int main() 
{
    scope_guard _{K{}};
}
Run Code Online (Sandbox Code Playgroud)

这个特色设计是否能够防止推断出本地类型?

或者这是gcc当前实现该功能的缺陷?

Bar*_*rry 7

这是当前实现中的一个错误:77890(NEW表示有效性,而不是在7.0中修复的UNCONFIRMED).能够演绎lambda是原始论文的一个激励性例子,如果它不起作用会很尴尬:

// Virtually impossible to pass a lambda to a template class' constructor without declaring the lambda
for_each(vi2.begin(), vi2.end(), Foo<???>([&](int i) { ...}));
Run Code Online (Sandbox Code Playgroud)
for_each(vi.begin(), vi.end(), Foo([&](int i) { ...})); // Now easy instead of virtually impossible
Run Code Online (Sandbox Code Playgroud)

我们可以创建一个非常基本的例子:

template <typename TF>
struct scope_guard
{
    scope_guard(TF ) { }
};

int main()
{
    scope_guard _([]{});
}
Run Code Online (Sandbox Code Playgroud)

这应该对由函数组成的综合函数集执行重载解析:

template <class TF> scope_guard<TF> synthesized(TF );
template <class TF> scope_guard<TF> synthesized(scope_guard<TF> const& );
template <class TF> scope_guard<TF> synthesized(scope_guard<TF>&& );
Run Code Online (Sandbox Code Playgroud)

这应该选择所述第一过载,并使用该返回类型的类型_,与TF感型拉姆达的.这应该都有效.