在 lambda 参数中使用 type_identity_t

Use type_identity_t in a lambda argument

提问人:ByteEater 提问时间:11/14/2023 更新时间:11/14/2023 访问量:69

问:

我正在尝试在表达式中重新实现 Logan Smith 的 Cursed C++ Casts。我的方法是将匿名函数与:implicit_casttype_identity_t

#include <iostream>
using namespace std;
int main() {
  int i = 1;
  long j = 4;
  cout << max(j, []<class T>(type_identity_t<T> x) -> T { return x; }(i));
}

但它不起作用。编译器(gcc 13.2)抱怨:

<source>: In function 'int main()':
<source>:6:70: error: no match for call to '(main()::<lambda(std::type_identity_t<T>)>) (int&)'
    6 |   cout << max(j, []<class T>(type_identity_t<T> x) -> T { return x; }(i));
      |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~
<source>:6:18: note: candidate: 'template<class T> main()::<lambda(std::type_identity_t<T>)>'
    6 |   cout << max(j, []<class T>(type_identity_t<T> x) -> T { return x; }(i));
      |                  ^
<source>:6:18: note:   template argument deduction/substitution failed:
<source>:6:70: note:   couldn't deduce template parameter 'T'
    6 |   cout << max(j, []<class T>(type_identity_t<T> x) -> T { return x; }(i));
      |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~

可以挽救吗?或者我应该改用其他方法?

C++ 模板 lambda 类型转换

评论

4赞 HolyBlackCat 11/14/2023
C++ 不会根据返回值的使用方式进行模板参数推导。

答:

2赞 user17732522 11/14/2023 #1

正如视频所解释的那样,必须使用指定目标类型的显式模板参数来调用它。您的 lambda 调用缺少这一点。重点是让它不会被自动推断出来。它用于强制用户显式指定模板参数。它没有任何其他功能影响。implicit_casttype_identity_t<T>T

要使用显式模板参数调用 lambda,您需要编写

[]<class T>(type_identity_t<T> x) -> T { return x; }.operator()</*target type*/>(i)

评论

0赞 ByteEater 11/14/2023
或者我可以写.我正在寻找以某种方式推断目标类型的最通用的可能方法,以便在其他地方发生类型更改时代码继续工作。decltype(j){i}
1赞 user17732522 11/14/2023
@ByteEater是不一样的,因为它是直接列表初始化,而不是隐式转换。如果您实际上并不关心所使用的特定初始化形式,那么就足够了。Braced-init-lists 不是从中推导出来的。但是,如果您切换 和 的类型,这将不相同,因为这样它就变成了缩小转换,通常允许作为隐式转换,但具体而言,在列表初始化中不允许。decltype(j){i}{i}ij
0赞 ByteEater 11/14/2023
你是对的,这等效于这种特定情况,但你的 with 保留了 的关键特征。但它需要提及目标类型。我想要指出的是,结合您的代码:..operator()implicit_cast[]<class T>(type_identity_t<T> x) -> T { return x; }.operator()<decltype(j)>(i)
1赞 user17732522 11/14/2023
@ByteEater 是的,这有效,但如果您要追求普遍性,那么请注意所呈现的内容也有问题。例如,它可能会进行简单的隐式转换无法执行的额外构造函数调用。implicit_cast
1赞 user17732522 11/15/2023
@ByteEater 这是预期的,但也会有一个对返回值的移动/复制构造函数调用。因此,即使函数参数的正常隐式转换有效,它也不适用于不可移动的类型。