函数模板重载与类模板

Function template overloading vs class templates

提问人:wimalopaan 提问时间:9/16/2023 最后编辑:DailyLearnerwimalopaan 更新时间:9/16/2023 访问量:90

问:

函数模板可以通过使用不同的模板参数列表来重载(如果我解释正确的话 https://en.cppreference.com/w/cpp/language/function_template)。如果模板参数列表的参数类型或数量不同,则它们不等效,并且很容易实现重载解决。

因此,以下是函数模板的三个重载:foo()

template<typename T> 
auto foo(int v) { 
    return 1 * v;    
}
template<typename T, typename U> 
auto foo(int v) {
    return 3 * v;    
}
template<uint8_t N> 
auto foo(int v) { 
    return 2 * v;    
}

对于类模板,情况并非如此:

template<typename T> struct F;

//template<uint8_t N> struct F; // interpreted as redeclaration

我的问题是双重的:

  • 我对函数模板重载的简单解释是否正确,并且
  • 为什么对于类模板来说这是不可能的?
C++ Templates 重载 function-templates 类模板

评论

0赞 HolyBlackCat 9/16/2023
(1) 是的。(请注意,如果省略,有时可以推导出模板参数,这增加了更多的深度。 ̄\_(ツ)_/ ̄
0赞 SoronelHaetir 9/16/2023
请注意,类模板具有函数模板所不具备的部分专用化功能。这对只是允许以非常不同的方式进行超载。
0赞 HolyBlackCat 9/16/2023
@SoronelHaetir 可悲的是,专业化不允许重载不同类型的模板参数 ( vs )。:(typename Tauto T

答:

2赞 Jan Schultke 9/16/2023 #1

如果模板参数列表的参数类型或数量不同,则它们不等效,并且很容易实现重载解决。

您说得对,这使函数模板与众不同,并允许重载。 但是,函数模板中的参数数量或种类不会告诉您哪个参数将获胜或参与重载解决。

template <typename T, typename U> // (1)
void foo(std::pair<T, U>);

template <typename T> // has fewer template parameters than (1), but is more specialized
void foo(std::pair<T, int>);

template <typename T> // has fewer template parameters than (1), but is less specialized
void foo(T);

在大多数情况下,调用函数模板时无论如何都不会显式提供模板参数,例如 ,然后必须从函数参数中推导出参数。 具有不同数量或种类的模板参数仅意味着某些重载不会进入重载集,因为推导失败,例如 只能指(1),不能指其他重载。foo(my_pair)foo<int, float>

为什么对于类模板来说这是不可能的?

类模板已经具有部分排序机制,以便选择更专业的模板。但是,类模板上的模板参数集始终是相同的。

同时具有专业化的部分排序机制重载机制将创建一个极其复杂的系统;将有两个并行运行的排序机制,以确定重载的哪个专用化最专用。

如果类模板仅支持重载,那么它们将需要在主模板上进行某种扣除,例如

template <typename T, std::size_t N> // primary template
struct element_type<std::array<T, N>> { using type = T; };

老实说,事后看来,这可能是更好的语言设计。