问题
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...
回答1:
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.
回答2:
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');
来源:https://stackoverflow.com/questions/39067388/will-template-parameter-deduction-for-constructors-available-since-c17-allow-e