【发布时间】:2012-12-07 13:48:11
【问题描述】:
最小程序:
#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:
模板 struct enable_if;
如果 B 为真,std::enable_if 有一个公共成员 typedef 类型,等于 到 T;否则,没有成员 typedef。
enable_if 是一个结构。基本上,如果在 enable_if 的第一个模板参数中评估的表达式为真(在我上面的示例中,它是),那么将有一个公共成员 type 与第二个模板参数具有相同的类型.
对于enable_if<true, int>,enable_if::type 的类型是int。
【问题讨论】:
-
最后一个案例没有编译并不奇怪。当函数只接收一个时,您正在使用两个模板参数。
-
谢谢,我想我在那里复制了错误的案例。固定。
-
我是一个 C++ 菜鸟,所以不要苛责我...第一个示例不是因为您覆盖了第一个方法而起作用吗?我很想知道这个问题的答案。我计划明年学习 C++。
-
有人能解释一下“typename T::type s”是什么意思吗?
-
很好奇。为@Johannes 呐喊
标签: c++ templates overloading