P0091R3 ("Template argument deduction for class templates") was recently added to gcc
trunk and can be tested on wandbox.
Something I had in mind was the possibility of using it to implement a "scope guard" in very few lines of code:
scope_guard _([]{ cout << "hi!\n" });
I tried implementing it on wandbox...
template <typename TF>
struct scope_guard : TF
{
scope_guard(TF f) : TF{f} { }
~scope_guard() { (*this)(); }
};
int main()
{
scope_guard _{[]{}};
}
...but compilation failed with the following error:
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)} { }
^~~~~~~~~~~
I then tried using a non-lambda local type, and got the same error.
int main()
{
struct K { void operator()() {} };
scope_guard _{K{}};
}
Afterwards, I tried a non-local type, and it worked as expected.
struct K { void operator()() {} };
int main()
{
scope_guard _{K{}};
}
Is this featured designed in such a way that prevents local types from being deduced?
Or is this a defect in gcc
's current implementation of the feature?
Template argument deduction is used when selecting user-defined conversion function template arguments. A is the type that is required as the result of the conversion. P is the return type of the conversion function template.
An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template. is a template used to generate template classes.
In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
Templates can be template parameters. In this case, they are called template parameters. The container adaptors std::stack, std::queue, and std::priority_queue use per default a std::deque to hold their arguments, but you can use a different container.
This is a bug in the current implementation: 77890 (NEW implies validity, as opposed to UNCONFIRMED fixed in 7.0). Being able to deduce a lambda was one of the motivating examples of the original paper, so would be quite awkward if it didn't work:
// 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
We can create a really basic example:
template <typename TF>
struct scope_guard
{
scope_guard(TF ) { }
};
int main()
{
scope_guard _([]{});
}
This should perform overload resolution on the synthesized function set consisting of the functions:
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>&& );
which should pick the first overload and use that return type as the type of _
, with TF
being type of the lambda. This should all work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With