我有兴趣编写一个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::declval
和std::remove_reference
做类似的事情,但我无法编译。无论如何,它不会比上面更清洁。
C ++ 14是否提供任何非偷偷摸摸的方式将SpecialThing
类型转换为createThing
?或者失败了,一种比我的nullptr技巧更好的偷偷摸摸的方式?
(注意:我知道我可以通过其他方式解决这个问题;我只是想要了解语言,而不是克服严重的障碍。因此,上面的愚蠢代码通常会包含一个标准函数原因。)
答案 0 :(得分: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 */);
}