什么是非弱化背景?

时间:2014-08-11 14:16:09

标签: c++ templates

我最近接触过this question,答案可以归结为“这是一个非受限的背景”。

具体来说,第一个说它是这样的东西,然后重定向到“细节”的标准,而第二个引用标准,这至少可以说是神秘的。

有人可以向凡人解释,比如我自己,非受限情境是什么,它何时发生,为什么会发生?

1 个答案:

答案 0 :(得分:80)

演绎是指从给定参数确定模板参数类型的过程。它适用于函数模板auto和其他一些情况(例如部分特化)。例如,考虑:

template <typename T> void f(std::vector<T>);

现在,如果您说f(x),您宣布std::vector<int> x;,那么T推导int,您将获得专业化{{ {1}}。

为了使演绎有效,要推导的模板参数类型必须出现在可推导的上下文中。在此示例中,f<int>的函数参数是这样的可推导上下文。也就是说,函数调用表达式中的参数允许我们确定模板参数f应该是什么,以使调用表达式有效。

但是,还有 - 受限的上下文,其中不可能进行扣除。规范示例是&#34;显示在T左侧的模板参数:

::

在此函数模板中,函数参数列表中的template <typename> struct Foo; template <typename T> void g(typename Foo<T>::type); 位于非推导的上下文中。因此,您无法说T并推断g(x)。这样做的原因是没有&#34;向后对应&#34;在任意类型和成员之间 T之间。例如,您可以拥有专业化:

Foo<T>::type

如果您致电 template <> struct Foo<int> { using type = double; }; template <> struct Foo<char> { using type = double; }; template <> struct Foo<float> { using type = bool; }; template <> struct Foo<long> { int type = 10; }; template <> struct Foo<unsigned> { }; g(double{})有两种可能的答案,如果您拨打T,则无法接听答案。通常,类模板参数和类成员之间没有关系,因此您不能执行任何合理的参数推断。


有时候明确地抑制参数推断是有用的。例如,g(int{})就是这种情况。另一个例子是当您从std::forward转换为Foo<U>,或者其他转换时(想到Foo<T>std::string)。现在假设你有一个自由函数:

char const *

如果您致电template <typename T> bool binary_function(Foo<T> lhs, Foo<T> rhs); ,则扣除可能不明确,因此会失败。但是推导出一个参数并且推导另一个参数是合理的,从而允许隐式转换。现在需要明确的非推断上下文,例如:

binary_function(t, u)

(您可能遇到类似template <typename T> bool binary_function(Foo<T> lhs, typename std::common_type<Foo<T>>::type rhs) { return binary_function(lhs, rhs); } 等问题的演绎问题。)