I'm interested in writing a lambda function that will, among other things, call std::make_unique
. To call std::make_unique
I need a typename, but it would seem that in order to directly pass the typename into the lambda function, I would have to make the lambda variable a template:
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 */);
}
But my compiler (GCC 4.9.2) doesn't seem to like this. (I didn't really expect it to, though I know little enough about template variables that I couldn't be sure it wouldn't.)
Suppose I'm really determined to keep createThing
a local variable of lambda-function type. How cleanly can I manage to wrap std::make_unique
in this fashion? Here's the best I've got so far:
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 */);
}
It's wordy, but it isn't terribly hard to understand, and it compiles.
I think maybe I could do something similar with std::declval
and std::remove_reference
but I couldn't get that to compile. Anyway it wouldn't be much cleaner than the above.
Does C++14 provide any non-sneaky way to get the SpecialThing
type into createThing
here? Or failing that, a sneaky way that's better than my nullptr trick?
(Note: I know I could work around this in other ways; I'm just asking to learn about the language, not to get past a serious obstacle. Hence the silly code above that trivially wraps a standard function for no apparent reason.)
I would use a tag type:
#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 */);
}