问题描述
假设我有一个功能模板和各种“专门化”该模板的重载。在解决重载过程中,与模板版本相比,重载是更好的匹配,因此它们将始终获得优先级。
template <typename T>
void dispatch(T&& t) {
std::cout << "generic\n";
}
void dispatch(int) {
std::cout << "int\n";
}
dispatch(5); // will print "int\n"
dispatch(nullptr); // will print "generic\n";
现在我遇到的情况是,我拥有一个可以适用于整套(不相关)类型的专业化知识,但是满足了诸如以下概念的约束条件:
template <std::floating_point T>
void dispatch(T t) {
if constexpr(std::is_same_v<T,float>) std::cout << "float\n";
else std::cout << "unknown\n";
}
不幸的是,这种重载与一般情况是一样的,因此像dispatch(1.0f)
这样的调用是模棱两可的。当然,我可以通过为所有类型(我目前知道的)提供显式重载来解决此问题,但是由于实际应用程序中类型的数量很大(客户端可能会添加更多这种类型的概念),并且这些类型中的每一个类型都将非常相似(直到编译时已知的微小差异为止),这将是很多重复。
是否有办法为整个概念重载功能?
解决方法
受约束的功能模板只有在具有the same template-parameter-lists时才能击败不受约束的功能模板。因此,要么使通用值取一个值(使两者都取T
):
template <typename T>
void dispatch(T t) {
std::cout << "generic\n";
}
或者使浮点数成为转发参考(以使两者都采用T&&
):
template <typename T>
requires std::floating_point<std::remove_cvref_t<T>>
void dispatch(T&& t) {
if constexpr(std::is_same_v<T,float>) std::cout << "float\n";
else std::cout << "unknown\n";
}