以下类可以利用template argument deduction for class templates吗?
template <int I>
struct Number
{
/* appropriate constructor here */
};
通过“利用”我的意思是,有没有办法(隐式地或明确地)推导出I
的价值?示例用法如下:
Number a(3); // a's type is Number<3>
答案 0 :(得分:5)
类模板的模板参数推导可以推导非类型模板参数,但不是你想要的方式。
例如
template <std::size_t size>
struct ArrayWrapper {
ArrayWrapper(std::array<int, size> a);
};
int main() {
std:array<int, 5> a;
ArrayWrapper aw(a); // ok; declares ArrayWrapper<5>
}
但是在您的示例中,您尝试从参数的值推导出非类型模板参数。通常,C ++的模板推导系统不支持该类,无论是用于类模板还是用于任何其他上下文。
答案 1 :(得分:3)
构造函数的模板推导仍然是演绎 - 并且演绎都是关于类型的。推导值的唯一方法是该值是否是推导类型之一的非类型模板参数。因此,我们只需将3
从无聊的旧int
提升为复杂的现代std::integral_constant<int, 3>
:
template <int I> using int_t = std::integral_constant<int, I>;
template <int I> constexpr int_t<I> int_c;
template <int I>
struct Number {
Number(int_t<I> ) { }
};
int main()
{
Number n(int_c<3> );
}
值得注意的是,此功能的目的是避免重复写入类型(例如使用std::lock_guard
),或者命名类型的情况可能是不可能的(例如使用lambda构造的类模板特化) 。这些都不适用于这里。当你有一个值 - 那就是它,只需使用值:
Number<3> n;
与Number n{3}
相同数量的字符,这些字符不起作用,因此无法获得。
答案 2 :(得分:-2)
我正在分享我的(部分)解决方案:
#include <iostream>
#include <type_traits>
template <int I>
struct Number
{
// 1.
Number(int) {}
};
// 2.
template <int K> Number(std::integral_constant<int, K>) -> Number<K>;
int main()
{
Number a{std::integral_constant<int, 1>{}}; // look ma, no \<>/
(void)a;
return 0;
}
我们对上面编号的评论所做的是:
一个参数构造函数。当我们传递积分常量时,这可以作为转换构造函数(注释掉它并得到编译错误)
明确的扣除规则
所有这些购买我们的是声明Number
对象而不指定模板参数的能力,即仅仅让构造函数推导出它们。不幸的是,这个解决方案没有优雅,因为构造要求一个整数常量(然后隐式转换为整数):
Number a{std::integral_constant<int, 1>{}}; // a := Number<int>
更进一步的是设计一种简单的写作方式:
Number a{3};
但明确的扣除规则不适用于非类型模板参数,或者至少我不能欺骗它工作。