模板函数重载相同的签名,为什么这个工作? [英] Template function overloading with identical signatures, why does this work?

查看:155
本文介绍了模板函数重载相同的签名,为什么这个工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最少节目:

  #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\\\
,foo< int,std :: enable_if< true,int>>(x));

return 0;
}

输出:

  1 

为什么这不会导致编译错误?当生成模板代码时,函数 int foo(typename T :: type search) int foo(S& search)有相同的签名吗?



如果你改变模板函数的签名有点,它仍然有效(正如我预期的上面的例子) :

 模板< typename S,typename T& 
void foo(typename T :: type s){
printf(a\\\
);
}

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

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

 模板< typename S,typename T& 
void foo(typename T :: type s){
printf(a\\\
);
}

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

编译器错误(Clang):

  test.cpp:26:2:错误:调用'foo'是不明确的
foo< std :: enable_if< true,int>> );
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:16:6:注意:候选函数[with T = std :: __ 1 :: enable_if< true,int>]
void foo(typename T :: type s){
^
test.cpp:21:6:note :候选函数[with T = std :: __ 1 :: enable_if< true,int>]
void foo(int s){
^
产生1个错误。

我正在使用类似于这个项目的代码,我害怕有一个微妙的语言,我不明白,将导致一些未定义的行为在某些情况下。我还应该提到它在Clang和VS11上编译,所以我不认为这只是一个编译器错误。






Edit:Corrected second case(typo);



编辑#2:对于那些询问T :: type意味着什么的人。



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


模板< bool B,class T = void>
struct enable_if;



如果B为真,std :: enable_if有一个public成员typedef类型,等于
至T;否则,没有成员typedef。


enable_if是一个结构体。基本上,如果在enable_if的第一个模板参数中求值的表达式为true(在我的上面的例子的情况下,它是),那么将有一个public成员 type



enable_if 的情况下, ,enable_if :: type的类型为int。

解决方案

第一个函数被认为比第一个函数更专业。 / p>

函数

  int foo(typename T :: type)

可以匹配

  template< typename S,typename T>通过使用T :: type作为参数S的值,但是使用T ::类型的int foo(S s)



  int foo(S s)

不匹配

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

因为T无法推导。



这个逻辑是在C ++ 03标准中的14.5.5.2节和在C ++ 11标准的14.5.6.2节中。



这里是想法:要查看一个函数是否比另一个更专业,您为第一个函数的每个模板参数创建值,然后查看第二个函数是否可以匹配结果签名。您还为第二个函数的模板参数创建值,并查看第一个函数是否匹配结果签名。如果第二函数可以匹配第一函数,则第二函数不能比第一函数更专门化。如果,除此之外,第一个函数不能匹配第二个,那么第一个函数必须比第二个更专门。这是你有的情况。


Minimal program:

#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;
}

output:

    1 

Why doesn't this give a compile error? When the template code is generated, wouldn't the functions int foo(typename T::type search) and int foo(S& search) have the same signature?

If you change the template function signatures a little bit, it still works (as I would expect given the example above):

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");
}

Yet this doesn't and yet the only difference is that one has an int signature and the other is defined by the first template parameter.

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");
}

Compiler error (Clang):

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.

I'm using code similar to this for a project I'm working on and I'm afraid that there's a subtly to the language that I'm not understanding that will cause some undefined behavior in certain cases. I should also mention that it does compile on both Clang and in VS11 so I don't think it's just a compiler bug.


Edit: Corrected second case (typo); added error message from Clang.

Edit #2: For those of you that asked what T::type means.

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

template< bool B, class T = void > struct enable_if;

If B is true, std::enable_if has a public member typedef type, equal to T; otherwise, there is no member typedef.

enable_if is a struct. Basically, if the expression evaluated in the first template parameter of enable_if is true (and in the case of my examples above, it is), then then there will be a public member type that has the same type as the second template parameter.

In the case of enable_if<true, int>, enable_if::type has a type of int.

解决方案

The first function is considered to be more specialized than the first.

The function

int foo(typename T::type)

could match

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

by using T::type as the value for parameter S, but

int foo(S s)

will not match

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

because T cannot be deduced.

The logic is layed out in the C++03 standard in section 14.5.5.2, and in the C++11 standard in section 14.5.6.2.

Here is the idea: To see if one function is more specialized than another, you invent values for each template parameter for the first function, and then see if the second function could match the resulting signature. You also invent values for the template parameters of the second function, and see if the first function will match the resulting signature. If the second function can match the first one, then the second function can't be more specialized than the first one. If, in addition to that, the first function can't match the second, then the first must be more specialized than the second. That is the case you have.

这篇关于模板函数重载相同的签名,为什么这个工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆