将类型名传递到 lambda 的最干净方法是什么?

What's the cleanest way to pass a typename into a lambda?

本文关键字:方法 是什么 lambda 类型      更新时间:2023-10-16

我有兴趣编写一个lambda函数,除其他外,它将调用std::make_unique。要调用std::make_unique,我需要一个typename,但是为了将typename直接传递给lambda函数,我必须使lambda变量成为模板:

struct SpecialThing
{
    SpecialThing(/* some arguments */) {}
}
void f()
{
    template <typename Thing>
    auto createThing = [](auto&&... parameters)
    {
        return std::make_unique<Thing>(std::forward<decltype(parameters)>(parameters)...);
    };
    auto thing = createThing<SpecialThing>(/* some construction parameters */);
}

但是我的编译器(GCC 4.9.2)似乎不喜欢这样。(我并没有真正期望它会这样,尽管我对模板变量知之甚少,所以我不能确定它不会。)

假设我真的决定保持createThing的lambda函数类型的局部变量。以这种方式包装std::make_unique有多干净?这是目前为止我找到的最好的:

void f()
{
    auto createThing = [](auto dummyThingPointer, auto&&... parameters)
    {
        typedef typename std::remove_pointer<decltype(dummyThingPointer)>::type Thing;
        return std::make_unique<Thing>(std::forward<decltype(parameters)>(parameters)...);
    };
    auto thing = createThing(static_cast<SpecialThing*>(nullptr), /* some construction parameters */);
}

这是冗长的,但不是很难理解,它编译。

我想也许我可以做一些类似的std::declvalstd::remove_reference,但我不能得到编译。无论如何,它不会比上面的更干净。

c++ 14是否提供了任何非鬼鬼祟祟的方式来获得SpecialThing类型到createThing这里?或者失败了,一个比我的nullptr技巧更好的鬼鬼祟祟的方法?

(注意:我知道我可以用其他方法解决这个问题;我只是要求学习语言,不是为了克服一个严重的障碍。因此,上面的愚蠢代码毫无理由地简单地包装了一个标准函数。)

我将使用一个标签类型:

#include <memory>
struct SpecialThing
{
    SpecialThing(/* some arguments */) {}
};
template<typename T>
struct Tag {
    typedef T type;
};
void f()
{
    auto createThing = [](auto typeTag, auto&&... parameters)
    {
        return std::make_unique<typename decltype(typeTag)::type>(
                        std::forward<decltype(parameters)>(parameters)...);
    };
    auto thing = createThing(Tag<SpecialThing>{} /*, some construction parameters */);
}