C++ 函数模板重载:空括号与显式 int
C++ function template overload: empty braces vs explicit int
下面有一些非常基本的 C++ 函数模板重载解决方案示例(从实际代码中最小化)
struct S {
S() {}
S(int) {}
};
template <typename T = S>
void foo(T x) { std::cout << "S" << std::endl; }
template <>
void foo<S>(S x) { std::cout << "S spc" << std::endl; }
int main() {
foo({});
foo(0);
}
这里有两种情况。在第一种情况下,编译器应默认初始化某些东西(如 S),在第二种情况下将 int 转换为某些东西(如 S)
我相信在这两种情况下,专业化都会赢得重载,因为专业化完全匹配并且通过部分排序确实比主模板更专业 [temp.deduct.partial]
但是本例中的 clang 11 和 gcc 10.2 都同意在第二种情况下主模板获胜。这个错误是在两个编译器中还是(可能)我不了解 C++ 标准?
只有一个候选人参与过载决议:
template <typename T=S> void foo(T);
函数模板特化的选择发生在之后。在这种情况下,我们有:
foo({})
无法推导出 T
(因为 {}
没有类型),所以我们转而使用 [=12 的默认参数=],也就是 S
。这给了我们一个可行的候选人来调用 - foo<S>
.
一旦我们决定调用 foo<S>
,我们就会考虑专业化。有一个,所以选择它。这打印 "S spc"
foo(0)
可以推导出T
,T
是int
。这给了我们一个可行的候选人来调用 - foo<int>
。这个没有专门化,这个[误导性]打印"S"
(即使这里没有涉及S
)。
只有当实际模板参数无法推导或未明确提供时,默认模板参数才会起作用。
如果你连foo(0)
都想调用foo<S>
,你需要防止deduction成功pick int
。但在那个时候,为什么还要有一个模板,只有一个接受 S
.
的函数
下面有一些非常基本的 C++ 函数模板重载解决方案示例(从实际代码中最小化)
struct S {
S() {}
S(int) {}
};
template <typename T = S>
void foo(T x) { std::cout << "S" << std::endl; }
template <>
void foo<S>(S x) { std::cout << "S spc" << std::endl; }
int main() {
foo({});
foo(0);
}
这里有两种情况。在第一种情况下,编译器应默认初始化某些东西(如 S),在第二种情况下将 int 转换为某些东西(如 S)
我相信在这两种情况下,专业化都会赢得重载,因为专业化完全匹配并且通过部分排序确实比主模板更专业 [temp.deduct.partial]
但是本例中的 clang 11 和 gcc 10.2 都同意在第二种情况下主模板获胜。这个错误是在两个编译器中还是(可能)我不了解 C++ 标准?
只有一个候选人参与过载决议:
template <typename T=S> void foo(T);
函数模板特化的选择发生在之后。在这种情况下,我们有:
foo({})
无法推导出T
(因为{}
没有类型),所以我们转而使用 [=12 的默认参数=],也就是S
。这给了我们一个可行的候选人来调用 -foo<S>
.一旦我们决定调用
foo<S>
,我们就会考虑专业化。有一个,所以选择它。这打印"S spc"
foo(0)
可以推导出T
,T
是int
。这给了我们一个可行的候选人来调用 -foo<int>
。这个没有专门化,这个[误导性]打印"S"
(即使这里没有涉及S
)。
只有当实际模板参数无法推导或未明确提供时,默认模板参数才会起作用。
如果你连foo(0)
都想调用foo<S>
,你需要防止deduction成功pick int
。但在那个时候,为什么还要有一个模板,只有一个接受 S
.