提问人:carraro 提问时间:11/6/2023 更新时间:11/6/2023 访问量:89
C++ 中的模板匹配函数重载问题 20
Trouble with Template Matching Function Overloads in C++20
问:
我目前正在处理一个 C++20 项目,我需要使用模板匹配实现一系列重载函数。我正在尝试创建一组函数模板,这些模板可以区分不同类别的类型(例如,整型类型、浮点型和自定义类)并使用专门的算法处理每种类型。
但是,我遇到了一个问题,即编译器没有像我预期的那样选择最专业的模板重载。我简化了我的代码来说明这个问题:
#include <iostream>
#include <type_traits>
// Overload for integral types
template<typename T>
requires std::is_integral_v<T>
void process(T value) {
std::cout << "Integral: " << value << std::endl;
}
// Overload for floating-point types
template<typename T>
requires std::is_floating_point_v<T>
void process(T value) {
std::cout << "Floating-point: " << value << std::endl;
}
// Overload for custom class
class MyCustomClass {};
template<>
void process<MyCustomClass>(MyCustomClass value) {
std::cout << "MyCustomClass instance" << std::endl;
}
int main() {
process(10); // Should call the integral overload
process(3.14); // Should call the floating-point overload
process(MyCustomClass()); // Should call the custom class overload
}
当我使用 编译此代码时,我收到一个错误,表明编译器无法推断出正确的重载:g++ (GCC) 10.2.0
error: template-id ‘process’ for ‘void process(MyCustomClass)’ does not match any template declaration’
我正在寻找以下几点的指导:
- 为什么编译器没有为 选择正确的重载?
MyCustomClass
- 有没有更好的方法来为 C++20 中的这种基于类型的重载构建我的函数模板?
- 这个问题可能与我正在使用的概念有关,还是与我的函数模板专用化有关?
我已经检查了 CPPReference 和其他 Stack Overflow 问题,但没有找到解决我问题的解决方案。我正在用标志编译。-std=c++20
答:
1赞
Rerito
11/6/2023
#1
如注释中所述,当您对函数模板具有显式的“专用化”时,只需编写一个普通的非模板重载:
void process(const MyCustomClass& object)
{
// ...
}
但是,如果您有模板过载,请注意可能发生的完美匹配:
template< typename T >
void process(T&& obj) // generic implementation using perfect-forwarding
{
// ...
std::cout << "Generic template" << std::endl;
}
使用上述两个重载,以下调用:
process(MyCustomClass{});
MyCustomClass obj{};
process(obj);
将使用通用实现并打印,因为模板是完全匹配的(对于< - 注意第一种情况下的右值 ref 和第二种情况下的 for)。Generic template
MyCustomClass&&
MyCustomClass&
为避免这种情况,您必须禁用专用类型的 cv-ref 组合模板,例如:
template< typename T >
requires(!std::is_same_v< MyCustomClass, std::remove_cvref_t< T > >)
void process(T&& obj)
{
// ...
}
4赞
user12002570
11/6/2023
#2
问题在于,您的代码中没有显式专用的主模板!
这意味着,若要解决此错误,可以提供主模板,也可以将显式专用化更改为非模板重载。
方法 1
这里我们提供了一个主模板,如下所示:
//added this primary template
template<typename T>
void process(T);
//other code as before
方法 2
第二种方法是只提供一个普通的非模板重载,而不是一个显式的专用化:
//note the template<> has been removed from here
void process(MyCustomClass value) {
std::cout << "MyCustomClass instance" << std::endl;
}
评论
template<> void process<MyCustomClass>(MyCustomClass value)
->void process(MyCustomClass value)