最小程序:
#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");
}
编译器错误(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.
我正在为我正在处理的项目使用与此类似的代码,我担心在某些情况下我不理解的语言会导致一些未定义的行为。我还应该提到它确实可以在 Clang 和 VS11 上编译,所以我不认为这只是一个编译器错误。
编辑:更正了第二种情况(错字);添加了来自 Clang 的错误消息。
编辑#2:对于那些询问 T::type 是什么意思的人。
来自http://en.cppreference.com/w/cpp/types/enable_if:
模板< bool B,类 T = void > struct enable_if;
如果 B 为真,std::enable_if 有一个公共成员 typedef 类型,等于 T;否则,没有成员 typedef。
enable_if 是一个结构。基本上,如果在 enable_if 的第一个模板参数中评估的表达式为真(在我上面的示例中,它是),那么将有一个type
与第二个模板参数具有相同类型的公共成员。
在 的情况下enable_if<true, int>
, enable_if::type 的类型为 int。