Apart from the most obvious usage of template parameter deduction for constructors, I can imagine some more complex use cases where we deduce only part of the parameters of the template class e.g.:
std::pair<int> p(1, 2); // std::pair<int, int>
Although this construct would be natural consequence of the deduction of template parameters in functions I couldn't find any example of this kind of usage. Maybe it's because of the ambiguity in case of classes with variadic template arguments?
std::tuple<int> t(1, 2, 3); // std::tuple<int, int, int>
However this way introduced syntax wouldn't substitute too good "make_*" wrappers (cf. N3602) where the functionality is available for us...
Apparently not. P0091's introduction claims that it does, but the actual wording says quite differently:
A template-name corresponding to a class template followed by a parenthesized expression-list...
This rules out the use of a template-name + some arguments and a "parenthesized expression-list". It is also ruled out grammatically in other parts of the wording.
So no, it won't be possible to specify some arguments while deducing others.
Yes, but indirectly.
For other people who have a similar problem but want a valid work around, not a language lawyer:
This might be an esoteric example, but it actually matches very closely a real world application of this technique.
You use a deduction guide, from C++17 and an additional constructor which accepts a helper type. This is often still easier when you have a class with many many template arguments that should mostly be deduced.
https://en.cppreference.com/w/cpp/language/class_template_argument_deduction
template <std::size_t v>
struct SizeT{};
template <std::size_t v, typename T>
struct PrintToBuffer
{
T const Dunno;
PrintToBuffer(T const & pInput) :
Dunno(pInput)
{}
//This works for any class, as it just forwards to another constructor
template <typename ... Args>
PrintToBuffer(SizeT<v>, Args && ... pInput) :
PrintToBuffer(std::forward<Args>(pInput)...)
{}
void Print(std::array<char, v> & pOutput)
{
for (auto & c : pOutput)
c = Dunno;
}
};
This can be played around with here:
https://godbolt.org/z/E8d1Dt
EDIT, Adding an example for tuple
And for an example with tuple:
template <typename ... Args>
struct Types{};
template <typename ... T>
struct Tuple : std::tuple<T...>
{
using base_t = std::tuple<T...>;
using base_t::base_t;
template <typename ... Ignore>
Tuple(Types<Ignore...>, T && ... pInput) : base_t(std::forward<T>(pInput)...) {}
};
template <typename ... Defined, typename ... Args>
Tuple(Types<Defined...>, Defined && ..., Args&& ...) -> Tuple<Defined..., Args...>;
With the compiler explorer here, note that both the deduced and defined template arguments are correctly constructed:
https://godbolt.org/z/VrT9Lf
Usage:
auto my_tuple = Tuple(Types<int, short>{}, 1, 1, 'a');
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