简体   繁体   English

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

[英]Can C++17's “template argument deduction” for class templates deduce local types?

P0091R3 ("Template argument deduction for class templates") was recently added to gcc trunk and can be tested on wandbox . P0091R3 (“类模板的模板参数推导”)最近添加到gcc trunk ,可以在wandbox上测试。

Something I had in mind was the possibility of using it to implement a "scope guard" in very few lines of code: 我想到的是在很少的代码行中用它来实现“范围保护”的可能性:

scope_guard _([]{ cout << "hi!\n" });

I tried implementing it on wandbox ... 我尝试在wandbox上实现它 ...

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

int main() 
{
    scope_guard _{[]{}};
}

...but compilation failed with the following error: ...但编译失败,出现以下错误:

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)} { }
     ^~~~~~~~~~~

I then tried using a non-lambda local type , and got the same error. 然后我尝试使用非lambda本地类型 ,并得到相同的错误。

int main() 
{
    struct K { void operator()() {} };
    scope_guard _{K{}};
}

Afterwards, I tried a non-local type , and it worked as expected. 之后, 我尝试了非本地类型 ,它按预期工作。

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

int main() 
{
    scope_guard _{K{}};
}

Is this featured designed in such a way that prevents local types from being deduced? 这个特色设计是否能够防止推断出本地类型?

Or is this a defect in gcc 's current implementation of the feature? 或者这是gcc当前实现该功能的缺陷吗?

This is a bug in the current implementation: 77890 ( NEW implies validity, as opposed to UNCONFIRMED fixed in 7.0). 这是当前实现中的一个错误: 77890NEW表示有效性,而不是 7.0中修复的UNCONFIRMED )。 Being able to deduce a lambda was one of the motivating examples of the original paper, so would be quite awkward if it didn't work: 能够演绎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) { ...})); 
 for_each(vi.begin(), vi.end(), Foo([&](int i) { ...})); // Now easy instead of virtually impossible 

We can create a really basic example: 我们可以创建一个非常基本的例子:

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

int main()
{
    scope_guard _([]{});
}

This should perform overload resolution on the synthesized function set consisting of the functions: 这应该对由函数组成的综合函数集执行重载解析:

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>&& );

which should pick the first overload and use that return type as the type of _ , with TF being type of the lambda. 应该选择第一个重载并使用该返回类型作为_的类型,其中TF是lambda的类型。 This should all work. 这应该都有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM