C++20 concept / requires expression to test if generic lambda accepts type(C++20概念/需要表达式来测试泛型lambda是否接受类型)
问题描述
我试图在编译时验证给定的lambda是否接受某种类型(在我的示例代码中为Double)。只要lambda的签名明确指定了类型,它就可以工作。但是,只要我在签名中使用带有AUTO的泛型lambda,在计算Requires语句时就会出现编译错误。
以下代码片段说明了该问题(also on compiler explorer)
#include <concepts>
#include <iostream>
#include <string>
template<typename F>
concept accepts_double = requires(F f, double d) { f(d); };
struct Component{};
int main(){
auto f1 = [](double a){double b = a;};
auto f2 = [](std::string a){std::string b = a;};
auto f3 = [](auto a){std::string b = a;};
std::cout << std::boolalpha << accepts_double<decltype(f1)> << "
"; // expected true
std::cout << std::boolalpha << accepts_double<decltype(f2)> << "
"; // expected false
//This one gives the error:
std::cout << std::boolalpha << accepts_double<decltype(f3)> << "
"; // expected false, gives compilation error
}
我的印象是,Requires语句将验证f(D);是否为有效表达式,否则将返回FALSE。但是,当使用最新的GCC和clang进行编译时,我得到一个错误,指示它正在尝试计算函数体:
:13:38: error: no viable conversion from 'double' to 'std::string' (aka 'basic_string<char>')
我的问题有没有其他方法可以确保向lambda传递双精度值,或者是否将Requires语句限制为仅检查签名?
推荐答案
这是预期行为。
lambdaf3
声称接受任何。但是要测试它是否可以通过double
调用,我们需要实例化调用操作符。只有该实例化的直接上下文中的失败才算作替换失败--其中直接上下文基本上是与实际函数签名密切相关的任何东西。一旦我们进入调用操作符的主体,这就不再是直接的上下文了。我们必须实例化Body,这会失败(无法从double
构造string
),但这是一个严重的编译器错误。
换句话说,这对SFINAE不友好。
现在,需要实例化lambda主体的唯一原因是它返回
auto
,而我们需要知道返回类型。我们可以直接提供:auto f3 = [](auto a) -> void {std::string b = a;};
此处,accepts_double<decltype(f3)>
编译。但它给了true
!因为Lambda确实声称接受一切。这里根本没有任何限制。由于我们碰巧不必实例化正文,因此我们避免了编译失败。
如果我们希望确保编译并提供正确的答案,则需要添加该约束:
auto f3 = [](std::convertible_to<std::string> auto a) {std::string b = a;};
现在,我们实际上将参数限制为允许的类型集。这将编译并正确生成false
(当然,因为double
不能转换为std::string
)。
这篇关于C++20概念/需要表达式来测试泛型lambda是否接受类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++20概念/需要表达式来测试泛型lambda是否接受类型
基础教程推荐
- 如何在 C++ 中处理或避免堆栈溢出 2022-01-01
- 运算符重载的基本规则和习语是什么? 2022-10-31
- 调用std::Package_TASK::Get_Future()时可能出现争用情况 2022-12-17
- 如何定义双括号/双迭代器运算符,类似于向量的向量? 2022-01-01
- 什么是T&&(双与号)在 C++11 中是什么意思? 2022-11-04
- 您如何将 CreateThread 用于属于类成员的函数? 2021-01-01
- C++ 标准:取消引用 NULL 指针以获取引用? 2021-01-01
- C++,'if' 表达式中的变量声明 2021-01-01
- C++ 程序在执行 std::string 分配时总是崩溃 2022-01-01
- 设计字符串本地化的最佳方法 2022-01-01