C++17 的 "template argument deduction" for class 模板可以推导出本地类型吗?
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.
我想到的是使用它来实现一个
"scope guard" 在极少的代码行中:
scope_guard _([]{ cout << "hi!\n" });
我试过了implementing it on wandbox...
template <typename TF>
struct scope_guard : TF
{
scope_guard(TF f) : TF{f} { }
~scope_guard() { (*this)(); }
};
int main()
{
scope_guard _{[]{}};
}
...但编译失败并出现以下错误:
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)} { }
^~~~~~~~~~~
然后我尝试 using a non-lambda local type,但得到了同样的错误。
int main()
{
struct K { void operator()() {} };
scope_guard _{K{}};
}
之后,I tried a non-local type,按预期工作。
struct K { void operator()() {} };
int main()
{
scope_guard _{K{}};
}
这个特性的设计是为了防止局部类型被推导吗?
或者这是gcc
当前功能实现的缺陷吗?
这是当前实现中的一个错误: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) { ...}));
for_each(vi.begin(), vi.end(), Foo([&](int i) { ...})); // Now easy instead of virtually impossible
我们可以创建一个非常基本的示例:
template <typename TF>
struct scope_guard
{
scope_guard(TF ) { }
};
int main()
{
scope_guard _([]{});
}
这应该对由函数组成的综合函数集执行重载解析:
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>&& );
应该选择第一个重载并使用 return 类型作为 _
的类型,其中 TF
是 lambda 的类型。这应该都有效。
P0091R3 ("Template argument deduction for class templates") was recently added to gcc
trunk and can be tested on wandbox.
我想到的是使用它来实现一个 "scope guard" 在极少的代码行中:
scope_guard _([]{ cout << "hi!\n" });
我试过了implementing it on wandbox...
template <typename TF>
struct scope_guard : TF
{
scope_guard(TF f) : TF{f} { }
~scope_guard() { (*this)(); }
};
int main()
{
scope_guard _{[]{}};
}
...但编译失败并出现以下错误:
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)} { }
^~~~~~~~~~~
然后我尝试 using a non-lambda local type,但得到了同样的错误。
int main()
{
struct K { void operator()() {} };
scope_guard _{K{}};
}
之后,I tried a non-local type,按预期工作。
struct K { void operator()() {} };
int main()
{
scope_guard _{K{}};
}
这个特性的设计是为了防止局部类型被推导吗?
或者这是gcc
当前功能实现的缺陷吗?
这是当前实现中的一个错误: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) { ...}));
for_each(vi.begin(), vi.end(), Foo([&](int i) { ...})); // Now easy instead of virtually impossible
我们可以创建一个非常基本的示例:
template <typename TF>
struct scope_guard
{
scope_guard(TF ) { }
};
int main()
{
scope_guard _([]{});
}
这应该对由函数组成的综合函数集执行重载解析:
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>&& );
应该选择第一个重载并使用 return 类型作为 _
的类型,其中 TF
是 lambda 的类型。这应该都有效。