【问题标题】:Why cannot C type-generic expressions be compatible with C++?为什么 C 类型泛型表达式不能与 C++ 兼容?
【发布时间】:2014-01-11 10:18:11
【问题描述】:

我似乎记得从一些可靠的消息来源(即委员会成员在非官方渠道中发言)那里听到模糊的 cmets,即 C 类型泛型表达式不会添加到 C++ 中,因为它们不能。

据我所知,与 C++ 模板和重载相比,类型泛型表达式非常有限,但没有可能需要将交互定义为特殊情况。

类型泛型表达式由控制表达式以及类型和子表达式之间的一系列“关联”组成。根据控制表达式的静态类型和为子表达式列出的类型来选择子表达式,并用它代替 TGE。匹配是基于 C 的类型兼容性概念,据我所知,这相当于 C++ 在单一定义规则 (ODR) 下具有 extern 链接的类型标识。

如果派生类控制表达式在 C++ 中选择基类关联,那就太好了,但由于 C 没有继承,因此交叉兼容性不需要这种精确性。这算不算绊脚石?

编辑:至于更具体的细节,C11 已经提供了保留所选子表达式的值类别(左值),并且似乎要求 TGE 是一个常量表达式(无论category) 只要它的所有操作数都是,包括控制表达式。这可能是 C 语言的缺陷。在任何情况下,C++14 都根据可能被评估的内容定义了常量表达式,并且 TGE 规范已经说过未选择的子表达式是不被评估的。

关键是 TGE 的操作原理看起来很简单,可以移植,以后不会造成麻烦。

至于为什么 C++ TGE 会很有用,除了最大化 C 和 C++ 的交集之外,它们还可以用来基本上实现 static_if,没有备受争议的条件声明功能。我不是static_if 的支持者,但“就是这样。”

template< typename t >
void f( t q ) {
    auto is_big = _Generic( std::integral_constant< bool, sizeof q >= 4 >(),
        std::true_type: std::string( "whatta whopper" ),
        std::false_type: "no big deal"
    );
    auto message = _Generic( t, double: "double", int: 42, default: t );
    std::cout << message << " " << is_big << '\n';
}

【问题讨论】:

  • 也许负责解决泛型的事情必须先于弄清楚类如何工作的事情。因此,您将无法泛化类,因此您将拥有仅适用于某些类型的功能。
  • @leewangzhong 嗯,它的工作方式与 C 中的相同。它适用于所有类型,只是不能深入了解继承。
  • 我的意思是,在解析泛型时可能无法识别 C++ 类型。
  • @leewangzhong:C++ 必须指定_Generic 的工作方式,C++ 肯定会指定它在识别 C++ 类型后解决。 (无论如何,这还很早,因为解析需要它。有关更多详细信息,请参阅“最令人烦恼的解析”。)
  • 你能告诉我们不可能的消息来源吗?上下文可能会有所帮助。

标签: c++ c c11


【解决方案1】:

“不可能”可能太强了。 “不确定是否可能”更有可能。

如果要将此功能添加到 C++ 中,则应完全指定它,包括与现有 C++ 功能的所有交互,其中许多功能在设计时并未考虑到 _Generic。例如。 typeid 在 C 中不存在,但应该在 C++ 中工作。你可以使用_Generic 表达式作为constexpr 吗?作为模板参数?是lvalue 吗?您可以获取它的地址并将其分配给函数指针,并获得重载解决方案吗?你能做模板参数推导吗?可以和auto一起使用吗?等等。

另一个复杂情况是_Generic 的主要用例是宏,它不能很好地与 C++ 命名空间配合使用。来自tgmathacos 示例就是一个明显的示例。 C++ 已经禁止 C 的标准宏并要求它们是函数,但这不适用于 tgmath.h

【讨论】:

  • 这些听起来更像是刻度线,需要检查是否没有交互。这个想法是选择一个子表达式并替换整个表达式。因此,似乎没有与您提到的任何事情进行交互的空间。至于 tgmath 宏,自 C++98 以来,它们已经被重载集所取代。
猜你喜欢
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
  • 2019-09-06
  • 1970-01-01
  • 2018-08-16
  • 2015-08-11
  • 1970-01-01
相关资源
最近更新 更多