基于依赖类型的存在重载
Overload based on existence of dependent type
我有两个同名的模板函数 (foo
)。它们的签名仅在第二个参数的类型上有所不同,这取决于模板参数 T
。令我感到惊讶的是,我可以根据 T::A
或 T::B
是否存在类型来使用它来重载。这是标准中专门规定的东西吗(如果是这样,将不胜感激),还是我只是很笨,没有将其识别为基本的重载解决方案?
#include <iostream>
using namespace std;
template<typename T>
void foo(T t, typename T::A* a = 0) {
cout << "Had an A" << endl;
}
template<typename T>
void foo(T t, typename T::B* b = 0) {
cout << "Had a B" << endl;
}
struct HasAnAType {
typedef int A;
};
struct HasABType {
typedef int B;
};
struct HasAAndBTypes {
typedef int A;
typedef int B;
};
int main() {
HasAnAType a;
HasABType b;
HasAAndBTypes ab;
foo(a); // prints "Had an A"
foo(b); // prints "Had a B"
foo(ab); // won't compile: 'ambiguous call to overloaded function'
}
作为背景,我在研究 std::enable_shared_from_this
的实现时发现这是可能的,它依赖于这种类型的重载。
你是对的,这不是 'regular' 重载。它被称为 SFINAE。更多信息在这里:https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
感谢 SFINAE,重载 void foo(T t, typename T::B* b = 0)
在 T::B
不存在时被 移除(类似于 T::A
)
所以当两者都可用时,两个重载都是可行的,所以调用是不明确的。
规范是这样定义重载决议的:
Overload resolution is a mechanism for selecting the best function to
call given a list of expressions that are to be the arguments of the
call and a set of candidate functions that can be called based on the
context of the call.
the selection of the best function is the same in all cases: First, a
subset of the candidate functions (those that have the proper number
of arguments and meet certain other conditions) is selected to form a
set of viable functions. Then the best viable function is selected
based on the implicit conversion sequences needed to match each
argument to the corresponding parameter of each viable function.
对于模板函数,还有附加规则:
For each function template, if the argument deduction and checking
succeeds, the template arguments (deduced and/or explicit) are used to
synthesize the declaration of a single function template
specialization which is added to the candidate functions set to be
used in overload resolution. If, for a given function template,
argument deduction fails, no such function is added to the set of
candidate functions for that template.
这些规则导致所谓的 SFINAE,以防模板函数的重载解析。
我有两个同名的模板函数 (foo
)。它们的签名仅在第二个参数的类型上有所不同,这取决于模板参数 T
。令我感到惊讶的是,我可以根据 T::A
或 T::B
是否存在类型来使用它来重载。这是标准中专门规定的东西吗(如果是这样,将不胜感激),还是我只是很笨,没有将其识别为基本的重载解决方案?
#include <iostream>
using namespace std;
template<typename T>
void foo(T t, typename T::A* a = 0) {
cout << "Had an A" << endl;
}
template<typename T>
void foo(T t, typename T::B* b = 0) {
cout << "Had a B" << endl;
}
struct HasAnAType {
typedef int A;
};
struct HasABType {
typedef int B;
};
struct HasAAndBTypes {
typedef int A;
typedef int B;
};
int main() {
HasAnAType a;
HasABType b;
HasAAndBTypes ab;
foo(a); // prints "Had an A"
foo(b); // prints "Had a B"
foo(ab); // won't compile: 'ambiguous call to overloaded function'
}
作为背景,我在研究 std::enable_shared_from_this
的实现时发现这是可能的,它依赖于这种类型的重载。
你是对的,这不是 'regular' 重载。它被称为 SFINAE。更多信息在这里:https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
感谢 SFINAE,重载 void foo(T t, typename T::B* b = 0)
在 T::B
不存在时被 移除(类似于 T::A
)
所以当两者都可用时,两个重载都是可行的,所以调用是不明确的。
规范是这样定义重载决议的:
Overload resolution is a mechanism for selecting the best function to call given a list of expressions that are to be the arguments of the call and a set of candidate functions that can be called based on the context of the call.
the selection of the best function is the same in all cases: First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions. Then the best viable function is selected based on the implicit conversion sequences needed to match each argument to the corresponding parameter of each viable function.
对于模板函数,还有附加规则:
For each function template, if the argument deduction and checking succeeds, the template arguments (deduced and/or explicit) are used to synthesize the declaration of a single function template specialization which is added to the candidate functions set to be used in overload resolution. If, for a given function template, argument deduction fails, no such function is added to the set of candidate functions for that template.
这些规则导致所谓的 SFINAE,以防模板函数的重载解析。