[英]C++20 NTTP specialization
There is disagreement between gcc/clang and msvc when trying to compile the following code:尝试编译以下代码时,gcc/clang 和 msvc 之间存在分歧:
struct foo {
};
// primary template
template<auto>
struct nttp {
static constexpr int specializaion = 0;
};
// specialization
template<foo f>
struct nttp<f> {
static constexpr int specializaion = 1;
};
int main() {
// Does not compile with msvc 19.30
nttp<5> x{};
}
Msvc is complaining that there is no viable conversion from int
to foo
which is obviously true, but shouldn't be of any relevance here as far as I understand the rules of partial template specialization. Msvc 抱怨没有从
int
到foo
的可行转换,这显然是正确的,但据我了解部分模板专业化的规则,这里不应该有任何相关性。
Quoting cppreference :引用cppreference :
When a class or variable (since C++14) template is instantiated, and there are partial specializations available, the compiler has to decide if the primary template is going to be used or one of its partial specializations.
当 class 或变量(C++14 起)模板被实例化,并且有部分特化可用时,编译器必须决定是使用主模板还是它的部分特化之一。
- If only one specialization matches the template arguments, that specialization is used
如果只有一个特化与模板 arguments 匹配,则使用该特化
- If more than one specialization matches, partial order rules are used to determine which specialization is more specialized.
如果匹配多个特化,则使用偏序规则来确定哪个特化更特化。 The most specialized specialization is used, if it is unique (if it is not unique, the program cannot be compiled)
使用最专业的特化,如果是唯一的(如果不是唯一的,程序无法编译)
- If no specializations match, the primary template is used
如果没有匹配的特化,则使用主模板
I'd argue that there is no matching spezialization for int
in this case hence the primary template should be selected.我认为在这种情况下
int
没有匹配的特殊化,因此应该选择主模板。
Interestingly, the situation can be fixed by constraining the auto
in the specialization by a concept:有趣的是,这种情况可以通过一个概念来限制
auto
的专业化:
template<class T>
concept Foo = std::is_same_v<T, foo>;
template<auto>
struct nttp {
static constexpr int specializaion = 0;
};
template<Foo auto f>
struct nttp<f> {
static constexpr int specializaion = 2;
};
// compiles with all compilers
static_assert(nttp<5>{}.specializaion == 0);
Function templates work as expected, too: Function 模板也可以按预期工作:
constexpr int test(auto) {
return 0;
}
constexpr int test(foo) {
return 1;
}
// compiles with all compilers
static_assert(test(5) == 0);
Long story short: empirically and intuitively I'd say that this is a bug in MSVC, but as always there's a chance that UB is involved here.长话短说:凭经验和直觉我会说这是 MSVC 中的一个错误,但与往常一样,UB 有可能在这里涉及。 So the question would be: are clang/gcc correct, or MSVC, or even all of them?
所以问题是:clang/gcc 是正确的,还是 MSVC 正确的,甚至全部正确?
This is open MSVC bug report:这是开放的 MSVC 错误报告:
Your program is well-formed as per [temp.class.spec.match]/2 and [temp.class.spec.match]/3 :根据[temp.class.spec.match]/2和[temp.class.spec.match]/3 ,您的程序格式正确:
/2 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, and the deduced template arguments satisfy the associated constraints of the partial specialization, if any.
/2 如果可以从实际模板参数列表中推导出部分特化的模板 arguments,并且推导出的模板 arguments 满足部分特化的相关约束(如果有),则部分特化匹配给定的实际模板参数列表。
/3 If the template arguments of a partial specialization cannot be deduced because of the structure of its template-parameter-list and the template-id, the program is ill-formed.
/3 如果偏特化的模板arguments由于其模板参数列表和模板id的结构而无法推导,则程序是非良构的。
/3 was specifically updated as part of P0127R2 ( Declaring non-type template parameters with auto
), which re-wrote the previously revised wording from the resolution of CWG1315 /3 作为P0127R2 (使用
auto
声明非类型模板参数)的一部分进行了特别更新,它重写了CWG1315决议中先前修订的措辞
(After CWG1315, before P0123R2) /3 Each template-parameter shall appear at least once in the template-id outside a non-deduced context.
(在 CWG1315 之后,在 P0123R2 之前) /3 每个模板参数应在非推导上下文之外的模板 ID 中至少出现一次。
This re-write was done particularly to allow partial specialization over non-template parameters declared with the auto
placeholder type.这种重写特别是为了允许对使用
auto
占位符类型声明的非模板参数进行部分特化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.