这是一些有效的语法:
std::uniform_real_distribution<> randomizer(0, 100);
它是如何工作的,它会自动推导出对象模板吗?为什么类型末尾需要写
<>
?我可以不去掉<>
就一样吗?
通常,当第一个参数和后续参数或唯一参数具有默认模板参数(如果是整数,则为类型或值)时,可以使用此方法并起作用。另一种情况是存在模板参数包但它是空的。
仍然需要
<>
将其识别为模板类型。
在这种情况下,类型声明为;
template <class RealType = double>
class uniform_real_distribution;
因此,模板类
RealType
的默认
uniform_real_distribution
是
double
。相当于
std::uniform_real_distribution<double>
。
C++ WD n4527,§14.3/4(模板参数)
当使用模板参数包或默认的template-argument 时,template-argument 列表可以为空。在这种情况下,空的
<>
括号仍应用作template-argument-list。 [ 示例:template<class T = char> class String; String<>* p; // OK: String<char> String* q; // syntax error template<class ... Elements> class Tuple; Tuple<>* t; // OK: Elements is empty Tuple* u; // syntax error
-结束示例]
template<class RealType = double>
class uniform_real_distribution;
如您所见,它具有类型为
double
std::uniform_real_distribution<> randomizer(0, 100);
相当于
std::uniform_real_distribution<double> randomizer(0, 100);
<>
也是没有必要。 来自
C++WD n3797 § 14.8.2(模板参数推导)
当引用函数模板特化时,所有 模板参数应该有值。这些值可以明确地 指定,或在某些情况下,从使用中推断或从 默认模板参数。所以这个编译得很好。
template <typename T>
T add(const T &t1, const T &t2) {
return t1 + t2;
}
int x = add(1, 7);
double y = add(1.5, 2.3);
模板参数推导尝试确定模板参数 (类型模板参数Ti的类型,模板模板的模板 模板参数 TTi 和非类型模板参数的值 ii),可以将其代入每个参数P以产生 类型推导 A,与参数 A 的类型相同,之后 下面列出了调整。但是在如果有多个参数,则分别推导每个P/A对 然后将推导的模板参数组合起来。如果扣除 对于任何 P/A 对失败或不明确,或者不同对产生 不同的推导模板参数,或者如果有任何模板参数 既没有推论也没有明确指定,编译失败。
某些上下文中编译器无法推导出模板参数。例如,这两个实例都无法编译。
template <typename T>
T add(const T &t1, const T &t2) {
return t1 + t2;
}
double x = add(3.141, 10);
template<std::size_t N>
void f(std::array<int, 2 * N> a);
std::array<int, 10> a;
f(a);
// note: f(std::array<int, N> a) would be able to deduce N
类模板类模板参数推导(CTAD),它使编译器也可以从类实例化的初始化值中推导模板参数。与函数模板类似,即使没有 <>
,编译器也会尝试推断模板参数。 在 C++17 中编译没有任何错误。
array x{1, 2, 3};
std::pair p(2, 4.5); // deduces to std::pair<int, double> p(2, 4.5);
std::tuple t(4, 3, 2.5); // same as auto t = std::make_tuple(4, 3, 2.5);
std::less l; // same as std::less<void> l;
template<class T>
struct A
{
A(T, T);
};
auto y = new A{1, 2}; // allocated type is A<int>
您还可以在定义中提供模板推导指南,以帮助编译器推导某些特定情况的类型。
例如,C++17 编译器拒绝编译它,即使类型很明显。
template <typename T, typename U> struct Pair {
T first;
U second;
};
Pair<int, int> p1{1, 2}; // This is fine.
Pair p2{1, 2}; // This gives error in C++17
// Although from C++20 onwards this also compiles.
聚合的类模板参数推导通常需要用户定义的推导指南,直到 C++20。
template <typename T, typename U>
struct Pair
{
T first{};
U second{};
};
// A deduction guide for our Pair (needed in C++17 only)
// Pair objects initialized with arguments of type T and U should deduce to Pair<T, U>
template <typename T, typename U>
Pair(T, U) -> Pair<T, U>;
Pair<int, int> p1{ 1, 2 };
Pair p2{ 1, 2 };
仅当不存在模板参数列表时才执行类模板参数推导。如果指定了模板参数列表,则不会发生推导。这意味着它无法编译。
std::tuple<> t3(1, 2, 3); // Error: no matching constructor in tuple<>.
// No deduction performed.
std::tuple<int> t4(1, 2, 3); // Also error. All types not specified.
在您的情况下,std::uniform_real_distribution
定义指定了默认模板参数。
template< class RealType = double >
class uniform_real_distribution;
默认的 double
类型允许编译:
std::uniform_real_distribution<> randomizer(0, 100);