将类型名传递给 lambda 最简洁的方法是什么?

问题描述 投票:0回答:2

我有兴趣编写一个 lambda 函数,除其他外,该函数将调用

std::make_unique
。 要调用
std::make_unique
我需要一个类型名,但似乎为了将类型名直接传递到 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::declval
std::remove_reference
做类似的事情,但我无法编译它。 无论如何,它不会比上面干净多少。

C++14 是否提供任何非偷偷摸摸的方式将

SpecialThing
类型转换为
createThing
? 或者如果失败了,还有比我的 nullptr 技巧更好的偷偷摸摸的方法吗?

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

c++ templates lambda c++14
2个回答
5
投票

我会使用标签类型:

#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 */);
}

0
投票

根据 cppreference/lambda:在 C++23 中引入了将

typename T
添加到 lambda 表达式的可能性。

示例代码:

    auto printThing = []<typename Thing>(Thing t) { std::cout << t << std::endl; };
    printThing(4);
© www.soinside.com 2019 - 2024. All rights reserved.