简体   繁体   English

C++20 NTTP 专业化

[英]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{};
}

Full example here .完整的例子在这里

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 抱怨没有从intfoo的可行转换,这显然是正确的,但据我了解部分模板专业化的规则,这里不应该有任何相关性。

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 起)模板被实例化,并且有部分特化可用时,编译器必须决定是使用主模板还是它的部分特化之一。

  1. If only one specialization matches the template arguments, that specialization is used如果只有一个特化与模板 arguments 匹配,则使用该特化
  2. 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)使用最专业的特化,如果是唯一的(如果不是唯一的,程序无法编译)
  3. 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.

相关问题 在 C++20 NTTP 和类型之间转换 - Convert between C++20 NTTP and type 使用 C++20 概念/要求 function 部分专业化 - Using C++20 concept/requires for function partial specialization 使用 C++20 概念模板 function 特化时的依赖关系 - Dependencies when using C++20 conceptual template function specialization 如何在 c++/c++20 中创建 function 的模板化模板特化? - How do I create a templated template specialization of a function in c++/c++20? 在C ++ 20中,不再允许在std中为程序定义类型专门化函数模板吗? - Will specialization of function templates in std for program-defined types no longer be allowed in C++20? C++20 概念:当模板参数符合多个概念时,选择哪个模板特化? - C++20 Concepts : Which template specialization gets chosen when the template argument qualifies for multiple concepts? C++20 中的无宏日志和跟踪,具有概念和模板专业化 - Macro-free Logging and Tracing in C++20, with concepts and template specialization C++20 中非类型文字参数的模板部分特化:clang 和 gcc 不一致 - Partial specialization of templates over non-type literal parameters in C++20: clang and gcc disagree 将 VSCode 更新为 C++20 - Update VSCode to C++20 C++20 中的指定初始化器 - Designated initializers in C++20
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM