为什么概念约束不被视为上下文类型信息?

问题描述 投票:0回答:1

考虑:

void f(int);        // (1)
void f(int, int);   // (2)


auto pf1 = static_cast< void (*)(int) >(f);      // Ok, address of (1)
auto pf2 = static_cast< void (*)(int, int) >(f); // Ok, address of (2)


static_assert(std::invocable<decltype(pf1), int>);      // passed
static_assert(std::invocable<decltype(pf2), int, int>); // passed
static_assert(!std::invocable<decltype(pf2), int>);     // passed

现在,我想使用概念来帮助编译器进行重载解析,而不是显式强制转换:

std::invocable<int> auto pf1 = f;  // Only (1) satisfies, there is no ambiguity

除非它无法编译。我的问题是为什么?

如果这个例子有效,我们就可以写:

std::string s;
std::ranges::transform(s, s.begin(), std::toupper);
c++ c++20 function-pointers c++-concepts overload-resolution
1个回答
0
投票

当前对声明的类型约束的唯一影响是隐式地

static_assert
推导出的类型就像没有类型约束一样满足约束。未指定它以任何方式影响重载解析或类型推导。

无论哪种方式,对于像

toupper
这样的标准库函数都没有帮助,因为它们中的大多数都没有被指定为addressable,这意味着您不知道使用什么重载结构来实现它们,因此不能保证您可以在任何情况下获取对它们的指针/引用。例如,
std::toupper
可以实现为单个函数模板而不是多个重载。那么仅仅检查约束不足以使你想要的工作起作用。您需要以某种方式进行模板参数推导,选择恰好使函数具有
int
的模板参数集。一般来说,这是一个无法判定的问题。

因此,我怀疑您是否能够提出合理的规则,将其添加到语言中以实际实现您想要的行为。

我认为可以添加一些内容,说明如果重载不满足类型约束,则将

f
的重载删除到
std::invocable<int> auto pf1 = f;
中。但是,如果将
f
实现为模板,这将无济于事,并且它也不适用于相同形式的函数参数,因为函数模板上的类型约束不与单个函数参数相关联,而是与整个函数模板相关联.

© www.soinside.com 2019 - 2024. All rights reserved.