为什么标准不允许模板参数列表中的常量依赖类型的初始化? [英] Why is initialization of a constant dependent type in a template parameter list disallowed by the standard?
问题描述
在此帖的回答中,(部分)专用于依赖类型的非类型模板参数,它表示:
In the answer to this post "(Partially) specializing a non-type template parameter of dependent type", it states:
专用的
非类型参数不取决于
专用化的参数。 [示例:
The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. [ Example:
template <class T, T t> struct C {};
template <class T> struct C<T, 1>; // error
template< int X, int (*array_ptr)[X] > class A {};
int array[5];
template< int X > class A<X,&array> { }; // error
-end example]
—end example ]
我的问题是为什么是这里的限制?有至少一个用例,我发现这个限制干扰写干净的代码。例如
My question is why is this restriction here? There is at least one use case where I find that this restriction interferes with writing clean code. E.g.
template <typename T, T*>
struct test;
template <typename T>
struct test<T, nullptr> // or struct test<T, (T*)nullptr>
{
};
template <typename R, typename...ARGs, R(*fn)(ARGs...)>
struct test<R(ARGs...), fn>
{
};
虽然我不确定是否有其他情况下说明基于类型的常数是一个问题
Though I'm unsure if there are other cases that stating a constant based on a type is a problem beyond not making any sense.
任何人都有理由说明为什么会这样。
Anyone have a reason for why this is so?
推荐答案
(IMHO)标准禁止特定功能的最常见原因是:
(IMHO) The most common reasons the standard disallows a specific feature are:
- 此功能由另一种机制覆盖
- 它与现有的语言逻辑和实现相矛盾,使其实现潜在地破坏代码。
- 旧版:该功能首先被遗漏,现在我们已经建立了很多功能,几乎被遗忘了(请参阅部分功能模板专业化)。
实现的难度很少是一个因素,虽然编译器实现可能需要一些时间来赶上硬东西的进化。
Difficulty of implementation is rarely a factor, though it may take some time for compiler implementations to catch up with evolution on the "hard" stuff.
您可以随时将非类型模板参数封装为另一种类型:
You could always wrap your non type template parameter in another type:
template < typename T1, typename T2 >
struct Demo {}; // primary template
template < typename T >
struct Demo<T, integral_constant<T, 0>> {}; // specialization
我怀疑这种黑客属于情况1.情况3总是一种可能性,所以让我们检查情况2.为了做到这一点,我们必须知道哪些是标准强加的相关规则类模板部分专门化。
I doubt this hack falls into case 1. Case 3 is always a possibility so lets examine case 2. To do this, we have to know which are the related rules the standard imposes on class templates partial specializations.
14.5.5 类模板部分专业化
-
非类型参数是非专用的,如果它是非类型参数的名称。所有其他非类型参数是专门的。 (C1)
在类模板部分专业化的参数列表中,适用以下限制:
Within the argument list of a class template partial specialization, the following restrictions apply:
- 部分专用的非类型参数表达式不涉及部分专门化的模板参数,除非参数表达式是简单标识符。 (C2)
- 与专门的非类型参数对应的模板参数的类型不取决于专业化的参数。 (C3)
- A partially specialized non-type argument expression shall not involve a template parameter of the partial specialization except when the argument expression is a simple identifier. (C2)
- The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. (C3)
我标记了我认为相关的前三个 C 笑话(第三个是有问题的)。根据C1在我们的情况下我们有一个专门的非类型参数,所以C2应该,但这
I marked the first three Clauses I found relevant (the third is the one in question). According to C1 in our case we have a specialized non-type argument so C2 should stand, yet this
template <class T, T t> struct C {};
template <class T> struct C<T, 1>;
实际上是
template <class T, T t> struct C {};
template <class T> struct C<T, T(1)>; // notice the value initialization
因此部分专用的非类型参数 T t
涉及除标识符之外的表达式中的部分专门化类T
的模板参数;此外,这样的专门化在值初始化中必然涉及类T
,其将总是违反规则。然后C3来了,为我们清除,使我们不必每次都扣除。
so the partially specialized non type argument T t
involves the template parameter of the partial specialization class T
in an expression other than an identifier; furthermore such specializations are bound to involve class T
in a value initialization which will always be a violation of the rules. Then C3 comes along and clears that out for us so that we won't have to make that deduction every time.
到目前为止,我们已经确定规则与自己同步,但这不会证明情况2(一旦我们删除了其他相关限制的初始限制) 。我们必须深入研究匹配类模板部分特化规则;部分排序在这里被认为超出了范围,因为如果我们可以产生有效的候选,那么由程序员把一个形成良好的程序放在一起(即不创建类模板的不明确的使用)。
So far we've established that the rules are in sync with themselves but this does NOT prove case 2 (once we remove the initial limitation every other related limitation falls apart). We'd have to dive into matching class template partial specializations rules; partial ordering is considered out of scope here because if we can produce valid candidates it's up to the programmer to put together a well formed program (i.e. not create ambiguous uses of class templates).
部分
类模板部分专业化的匹配[ class.spec.match]
描述模板专业化中涉及的模式匹配过程。规则 1
是过程的总体工作流程,后续规则是定义正确性的规则。
describes the (give or take) "pattern matching" process involved in template specialization. Rule 1
is the overall workflow of the procedure and the subsequent rules are those that define correctness
-
如果部分特化的模板参数可以从实际模板参数列表中推导出来,则部分特化与给定的实际模板参数列表匹配
A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list
非类型模板参数也可以从主模板的非类型参数的实际模板参数的值中推导出来。
A non-type template argument can also be deduced from the value of an actual template argument of a non-type parameter of the primary template.
在引用类模板特殊化的类型名称中(例如,A),参数列表应与主模板的模板参数列表匹配。专业化的模板参数是从主模板的参数中推导出来的。
In a type name that refers to a class template specialization, (e.g., A) the argument list shall match the template parameter list of the primary template. The template arguments of a specialization are deduced from the arguments of the primary template.
违反这些规则,方法是允许与专用非类型参数对应的模板参数的类型取决于专业化参数。所以IMHO 没有具体原因为什么我们不能在未来的语言版本中使用此功能:遗留问题。可悲的是,我没有找到任何语言建议,主动介绍这个功能。
These rules are not violated by allowing the type of a template parameter corresponding to a specialized non-type argument to be dependent on a parameter of the specialization. So IMHO there is no specific reason why we can't have this feature in future revisions of the language: legacy is to blame. Sadly I didn't manage to find any language proposals with the initiative to introduce this feature.
这篇关于为什么标准不允许模板参数列表中的常量依赖类型的初始化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!