语法存在以调用受限函数隐藏的无限制函数吗?

3

我知道在概念上,有限制的函数(无论实际上约束有多松)始终比无限制的函数更匹配。但是否有语法来选择性地调用下面示例代码中的无限制版本的 f()?如果没有,编译器是否应该警告不可调用的函数?

#include <iostream>

template <typename T> requires(true) 
void f() { std::cout << "Constrained\n"; }

template <typename T>
void f() { std::cout << "NOT Constrained\n"; }


int main() {
    f<int>();
}

https://godbolt.org/z/n164aTvd3


有没有语法可以选择性地调用f()的无限制版本?你想如何进行选择? - Nicol Bolas
1
定义看起来已经不规范了,NDR。模板头在功能上是等效的,但并不相同。https://www.eel.is/c++draft/temp#over.link-7 - user17732522
@user17732522 你确定这个条款适用吗?“如果程序的有效性或含义取决于两个结构是否等效,而它们在功能上是等效的但不等效,则程序是非法的,无需诊断。”在我的例子中,有效性并不取决于这两个结构是否等效。此外,https://www.eel.is/c++draft/temp#over.link-example-4显示了两个“相同”的函数,它们仅在约束方面有所不同,但明确标记为OK。(虽然它们本身不是模板,而是模板类的成员。) - Chris Uzdavinis
@NicolBolas 我想要的方式并不重要。 :) 我只是在问是否有一种方法,无论它是否是我想要的方式。我对语言的这个部分如何工作很好奇。这并不反映我正在解决的问题。但是,例如,可以使用显式命名空间限定符在命名空间中查找否则隐藏的函数,也许有一种类似的方法来选择特定的函数。 - Chris Uzdavinis
1
@ChrisUzdavinis 如果两个模板头部相等,那么您的示例将形式不正确,因为您会有两个相同实体的定义,因此其有效性取决于此。关于这个例子的问题很好。我不太确定为什么它也不被视为不正常,NDR。 - user17732522
1
@ChrisUzdavinis 我在这里发布了一个关于标准示例的问题链接 - user17732522
1个回答

4

同一个函数的不同重载版本意在完成相同的任务。它们可能采用不同的方式或作用于不同类型的对象,但在概念层面上,所有函数的重载版本都应该完成相同的任务。

这包括受限制的函数(constrained functions)。通过将受限的重载版本放入函数的重载集中,您声明了这是完成该重载集所做事情的有效替代方法。因此,如果约束匹配,则应调用该函数。就像常规函数重载中不同类型的参数一样。

如果您希望明确调用被约束隐藏的重载版本,则您的设计已经出现问题。或更具体地说,如果某个重载版本完全由一个或多个受限制的重载版本隐藏,那么显然您实际上比所需的多了一个重载版本。

如果约束条件匹配,调用方应完全可以接受受限制的重载版本。如果不是这种情况,则说明您的设计存在问题。

因此,没有机制可以绕过明确专门化模板(explicitly specialized template)并使用原始版本,即使您的模板参数与专门化版本匹配,也不能这样做。


1
我不同意设计问题以及所有情况的理由,例如对于模板和常规函数,可以这样使用 template <typename T> void f(T) {/*..*/} void f(int n) { /*some stuff*/ f<int>(n); } - Jarod42
ADL将名称放入重载集合中,但是有技巧可以禁用ADL查找符号。 我不认为我的问题要求什么过分的东西。也就是说,我要的东西在这里并不是问题,我的设计也不是问题。(事实上,我没有设计,而是挖掘需求并试图了解一些特殊情况。)我只想知道C++是否允许这样做,而与它是否是个好主意无关。 - Chris Uzdavinis
谢谢你的最后一段话。那就是我在寻找的答案。 :) - Chris Uzdavinis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接