模板函数重载具有相同的特征,为什么这项工作?(Template function overloadi

2019-08-04 09:21发布

最小的程序:

#include <stdio.h>

#include <type_traits>

template<typename S, typename T>
int foo(typename T::type s) {
    return 1;
}

template<typename S, typename T>
int foo(S s) {
    return 2;
}

int main(int argc, char* argv[]) {
    int x = 3;
    printf("%d\n", foo<int, std::enable_if<true, int>>(x));

    return 0;
}

输出:

    1 

为什么不给这个编译错误? 当生成模板代码,也不会功能int foo(typename T::type search)int foo(S& search)具有相同的签名?

如果要更改模板函数签名一点点,它仍然有效(因为我希望给上面的例子):

template<typename S, typename T>
void foo(typename T::type s) {
    printf("a\n");
}

template<typename S, typename T>
void foo(S s) {
    printf("b\n");
}

然而,这不,但唯一的区别是,一个有一个int签名,另一种是由第一个模板参数定义。

template<typename S, typename T>
void foo(typename T::type s) {
    printf("a\n");
}

template<typename S, typename T>
void foo(int s) {
    printf("b\n");
}

编译器错误(锵):

test.cpp:26:2: error: call to 'foo' is ambiguous
foo<std::enable_if<true, int>>(3);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:16:6: note: candidate function [with T = std::__1::enable_if<true, int>]
void foo(typename T::type s) {
        ^
test.cpp:21:6: note: candidate function [with T = std::__1::enable_if<true, int>]
void foo(int s) {
        ^
1 error generated.

我用类似这样的一个项目我工作的代码,我很害怕,有一个微妙地说我不理解,这将导致在某些情况下,一些不确定的行为语言。 我还要提到的,它并编译两个锵和VS11所以我不认为这只是一个编译器错误。


编辑:纠正第二种情况(错字); 从锵加入错误消息。

编辑#2:对于那些你问::类型的意思吨。

从http://en.cppreference.com/w/cpp/types/enable_if :

模板<布尔B,类T =空隙>结构enable_if;

如果B是真实的,性病:: enable_if有一个公共的typedef构件类型,等于T; 否则,没有任何成员的typedef。

enable_if是一个结构。 基本上,如果在enable_if的第一个模板参数评估表达式为真(在上述我的例子的情况下,它是),则然后将有一个公共成员type具有相同的类型与第二个模板参数。

在的情况下enable_if<true, int> ,enable_if ::类型具有int类型。

Answer 1:

第一个功能被认为是比第一个更专业化。

功能

int foo(typename T::type)

可以匹配

template <typename S,typename T> int foo(S s)

通过使用T ::类型作为参数S的值,但

int foo(S s)

不匹配

template <typename S,typename T> int foo(typename T::type)

因为T不能推断。

该逻辑在C ++ 03标准奠定了在第14.5.5.2,而在部分14.5.6.2的C ++ 11标准。

这里的理念是:要查看一个功能比另一种更专业,你发明值的第一个功能每个模板参数,再看看第二个功能可以匹配所产生的签名。 您还发明值的第二函数的模板参数,看看第一个函数将匹配得到的签名。 如果第二个功能,可以匹配第一个,然后第二个功能不能比第一个更加专业化。 如果,除了是,第一功能不能在第二场比赛,那么第一个必须比第二更加专业化。 这是你的情况。



Answer 2:

下面是该现象的进一步简化:

#include <stdio.h>

template<typename T>
void foo(int arg) {
    printf("a\n");
}

template<typename T>
void foo(T arg) {
    printf("b\n");
}

int main(int argc, char* argv[]) {
    foo<int>(3);   // prints "a"
    foo(3);        // prints "b"

    return 0;
}

模板参数既可以通过尖括号显式地传递或者他们可以通过扣来解决。 如果没有明确指定一个参数,则必须使用函数的参数是推断出来。

因此,在的情况下, foo(3)模板“一”是行不通的,因为参数T没有明确规定,不能推断。 在的情况下, foo<int>(3)这两个模板可以工作。 事实上,如果你注释掉模板'A',调用foo<int>(3)将打印“B”。 所以现在的问题是,为什么模板“A”者优先? 这里的关键是“偏序”:

http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fpartial_ordering_funct_templ.htm

我现在看到别人已经回答了(我在快速回答问题不好),所以我要去只是包装这件事,现在,说模板“一”是更专业的像沃恩说。



文章来源: Template function overloading with identical signatures, why does this work?