C++ C++;模板专门化优先级。模板化专门化

C++ C++;模板专门化优先级。模板化专门化,c++,templates,C++,Templates,这个主题看起来有点混乱,但我不知道如何更恰当地表达它,抱歉=) 让我们看看下面的代码 #包括 模板 空隙f(T值){ std::cout这里有UB 与类不同,模板函数不能部分专用。 模板函数可以像您编写的那样完全专用化 template<> void f(int value) { std::cout << "f<int>" << std::endl; } 模板 空f(整数值){ 让我们从一个简单的例子开始:f(123); 在模板void f(

这个主题看起来有点混乱,但我不知道如何更恰当地表达它,抱歉=)

让我们看看下面的代码

#包括
模板
空隙f(T值){
std::cout这里有UB

与类不同,模板函数不能部分专用。 模板函数可以像您编写的那样完全专用化

template<>
void f(int value) {
  std::cout << "f<int>" << std::endl;
}
模板
空f(整数值){

让我们从一个简单的例子开始:
f(123);

模板void f(typename S::type)
中,无法推断
T

所以只有一个可行的函数
f(T)
T=int

我们选择
f(T)
(选择只发生在主模板上) 它在专门化
f(int)
中解析

第二种情况:
f(123);

现在,这两种功能都是可行的:

  • template void f(typename S::type)
    with
    T=int
  • f(T)
    with
    T=int
第一个比第二个更专业,所以选择了第一个

注:

Gcc、Clang和Mscv对此表示同意。

我对您将如何使用SFINAE感兴趣?您有时间解释吗?@JerryJeremiah SFINAE很简单,但它的语法非常不友好。其想法是您添加额外的类型名,作为由其他人确定的条件-如果类型名被证明是不可编译的废话,那么e声明格式不正确且被忽略。你最好在网上寻找关于编写SFINEA代码的指南-关于这个主题有指南和视频。@JerryJeremiah如果你的意思与文章中的完全相同,那么它本质上是没有意义的。但是如果你只是想要一些没有格式错误的东西,那么就创造一些任意的条件在typename
T
上启用
A
,当
A
为true时启用第一个声明,当
A
为false时启用第二个声明。“部分专门化”往往会导致UB。模板重载一般来说是可以的,对
int
的别名会导致2
f(int)
这是有问题的。@Jarod42重载意味着您有同名但输入参数不同的函数。“部分专门化”这意味着您对同一模板对象有两个不同的定义,但其中一个定义比另一个定义更专业,因此是首选的。模板类支持它,但函数不支持。本文对此进行了介绍。这两个定义在功能上是等效的,因为“对于任何给定的模板参数集,对这两个表达式的求值都会得到相同的值”。然后:“如果程序包含功能等效但不等效的函数模板声明,则该程序的格式不正确;无需进行诊断。“如果
int
不应该,那么哪些类型应该使用S版本?您如何决定?”此行为是否记录为实现定义?“不,它可能是编译器中的错误”或者一个格式错误的程序NDR或UB。他们不同意。如果你简单地切换声明的顺序,结果就会改变。它只是UB。其他顺序给出相同的结果。conexpr应该避免UB,只保留格式错误的程序NDR。请学会检查你自己的声明@ALX23z:你不能写(完整)在泛型模板之前进行专门化。您的版本不会编译(不是因为
静态\u断言
)。它不会在MSVC上工作,因为它会创建链接器错误。这两个函数都会生成相同的符号,从而生成UB。此外,如果
f(123)
生成一个数字,但
f(123)
导致另一个数字已经是一个巨大的问题。在VS2019中,如果两个函数都使用,则它们都返回0,但如果只有一个函数,则它们将导致0或3。
_main   PROC
        ; ....
        push    123                           ; 0000007bH
        call    void f<int>(int)                      ; f<int>
        add     esp, 4
        push    123                           ; 0000007bH
        call    void f<int>(int)                      ; f<int>
        ; ...
template<>
void f(int value) {
  std::cout << "f<int>" << std::endl;
}
template<typename T>
void f(T value) {
  std::cout << "f<T>" << std::endl;
}

template<typename T>
void f(typename S<T>::type value) {
  std::cout << "f<S<T>>" << std::endl;
};
// These two are conflicting declarations for "f" and compiler has no way to disambiguate.
// Worse due to nature of templates it tends to fail to figure out that there is ambiguity. 
// How to differentiate the two anyways?