gpt4 book ai didi

c++ - SFINAE 自动检查函数体是否在没有明确约束的情况下编译

转载 作者:太空狗 更新时间:2023-10-29 19:45:16 26 4
gpt4 key购买 nike

如果函数体没有意义(即不编译),我经常使用 SFINAE 从重载集中删除函数。是否可以向 C++ 添加一个简单的 require 语句?

例如,让我们有一个函数:

template <typename T>
T twice(T t) {
return 2 * t;
}

然后我得到:

twice(1.0);
twice("hello"); // Error: invalid operands of types ‘int’ and ‘const char*’ to binary ‘operator*’

我想得到一个错误,指出没有函数 twice 用于 const char * 类型的参数

我很想写这样的东西:

template <typename T>
requires function_body_compiles
T twice(T t) {
return 2 * t;
}

然后我会得到

twice(1.0);
twice("hello"); // Error: no matching function for call to ‘twice2(const char [6])’

更多动力:我在看演讲The Nightmare of Move Semantics for Trivial Classes他的最终 SFINAE 基本上是在说:在编译时使用这个构造函数。对于更复杂的构造函数,编写正确的 SFINAE 将是一场噩梦。

您认为将 requires function_body_compiles 添加到 c++ 中是否有意义?还是我遗漏了一个基本问题?这会被滥用或误用到什么程度?

最佳答案

我们没有这个功能的最大原因是它很难。

这很难,因为它要求编译器能够编译几乎任意的 C++ 代码,得到错误,然后干净地退出。

现有的 C++ 编译器并非都设计用于执行此操作。事实上,MSVC 花了十年的大部分时间才获得合理兼容的 decltype SFINAE 支持。

对全功能机构这样做会更难。


现在,即使这很容易,也有理由不这样做。它以一种非常可怕的方式混合了实现和接口(interface)。

C++ 委员会没有走这条路,而是朝着完全不同的方向前进。

概念是指您可以以合理的、通常是命名的方式表达有关类型的要求。他们进来了 .

正如另一个答案提到的,

template <typename T> requires requires(T t) { { 2 * t } -> T; }
T twice(T t) {
return 2 * t;
}

是一种实现方式,但这种方式被认为是错误的形式。相反,你应该写一个概念“可以乘以一个整数并得到相同的类型”。

template<typename T>
concept IntegerScalable = requires(T t) {
{ 2 * t } -> T;
};

然后我们可以

template <IntegerScalable T>
T twice(T t) {
return 2 * t;
}

我们完成了。

期望的下一步称为“已检查的概念”。在已检查的概念中,该概念转换为您的类型 T 的一组编译时接口(interface)。

然后检查函数体以确保不对任何非概念要求的 T 类型执行任何操作。

使用理论上的 future 检查概念,

template <IntegerScalable T>
T twice(T t) {
T n = 7;
if (n > t) return n;
return 2 * t;
}

这会被编译器拒绝在编译模板时甚至在调用模板之前,因为概念IntegerScalable 不能保证你可以用整数初始化 T,也不能用 > 将一个 T 与另一个进行比较。另外,我认为以上内容需要移动构造。


今天你可以做一个 hack。

#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }

那么你的代码可以写成:

template<class T>
auto twice(T t)
RETURNS( 2 * t )

您将获得 twice 的 SFINAE 友好版本。它也将尽可能做到 noexcept。

@Barry 提出了使用 => 替换 RETURNS 和其他一些内容的变体,但我已经一年没有看到它移动了。

与此同时,RETURNS 完成了大部分繁重的工作。

关于c++ - SFINAE 自动检查函数体是否在没有明确约束的情况下编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53441832/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com