自 C++17 允许显式指定某些 class 模板参数以来,构造函数的模板参数推导是否可用?
Will template parameter deduction for constructors available since C++17 allow explicitly specify some of the class template arguments?
除了构造函数的模板参数推导的最明显用法外,我可以想象一些更复杂的用例,我们只推导模板的部分参数class例如:
std::pair<int> p(1, 2); // std::pair<int, int>
尽管这种构造是在函数中扣除模板参数的自然结果,但我找不到这种用法的任何示例。
也许是因为 classes 带有可变模板参数的情况下的歧义?
std::tuple<int> t(1, 2, 3); // std::tuple<int, int, int>
然而,这种引入语法的方式不会替代太好的 "make_*" 包装器(参见 N3602),其中功能对我们可用...
显然不是。 P0091 的介绍声称它确实如此,但实际的 措辞 却完全不同:
A template-name corresponding to a class template followed by a parenthesized expression-list...
这排除了模板名称 + 一些参数和 "parenthesized expression-list" 的使用。其他部分的写法也从语法上排除了。
所以不,在推导其他参数的同时指定一些参数是不可能的。
是的,但是是间接的。
对于有类似问题但想要有效解决方法而不是语言律师的其他人:
这可能是一个深奥的例子,但它实际上非常接近这种技术在现实世界中的应用。
您使用了来自 C++17 的演绎指南和一个接受辅助类型的附加构造函数。当你有一个 class 有许多模板参数时,这通常更容易推导。
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;
}
};
可以在这里玩:
编辑,为元组添加示例
以元组为例:
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...>;
使用此处的编译器资源管理器,请注意推导和定义的模板参数均已正确构造:
用法:
auto my_tuple = Tuple(Types<int, short>{}, 1, 1, 'a');
除了构造函数的模板参数推导的最明显用法外,我可以想象一些更复杂的用例,我们只推导模板的部分参数class例如:
std::pair<int> p(1, 2); // std::pair<int, int>
尽管这种构造是在函数中扣除模板参数的自然结果,但我找不到这种用法的任何示例。 也许是因为 classes 带有可变模板参数的情况下的歧义?
std::tuple<int> t(1, 2, 3); // std::tuple<int, int, int>
然而,这种引入语法的方式不会替代太好的 "make_*" 包装器(参见 N3602),其中功能对我们可用...
显然不是。 P0091 的介绍声称它确实如此,但实际的 措辞 却完全不同:
A template-name corresponding to a class template followed by a parenthesized expression-list...
这排除了模板名称 + 一些参数和 "parenthesized expression-list" 的使用。其他部分的写法也从语法上排除了。
所以不,在推导其他参数的同时指定一些参数是不可能的。
是的,但是是间接的。
对于有类似问题但想要有效解决方法而不是语言律师的其他人:
这可能是一个深奥的例子,但它实际上非常接近这种技术在现实世界中的应用。
您使用了来自 C++17 的演绎指南和一个接受辅助类型的附加构造函数。当你有一个 class 有许多模板参数时,这通常更容易推导。
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;
}
};
可以在这里玩:
编辑,为元组添加示例
以元组为例:
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...>;
使用此处的编译器资源管理器,请注意推导和定义的模板参数均已正确构造:
用法:
auto my_tuple = Tuple(Types<int, short>{}, 1, 1, 'a');