为什么C类型泛型表达式不能与C ++兼容? [英] Why cannot C type-generic expressions be compatible with C++?

查看:172
本文介绍了为什么C类型泛型表达式不能与C ++兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎回想起来,从几个可靠的来源(即委员会成员在非官方渠道中发言)的C类型泛型表达式不会添加到C ++,因为它们不能。



据我所知,与C ++模板和重载相比,类型泛型表达式非常有限,但是没有潜在的交互作用需要被定义为特殊情况。



类型泛型表达式由控制表达式和类型与子表达式之间的一系列关联组成。基于控制表达式的静态类型和为子表达式列出的类型来选择子表达式,并且替换TGE代替子表达式。匹配是基于类型兼容性的C概念,根据单一定义规则(ODR),我可以告诉它等同于具有 extern 链接的类型的C ++标识。 。



如果一个派生类控制表达式在C ++中选择一个基类关联,但是由于C没有继承,所以不需要这么好用于交叉兼容性。

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



点是,TGE操作原理似乎足够简单,可以移植,而不会在以后造成麻烦。



至于为什么 C ++ TGE ,除了最大化C和C ++的交集之外,它们可以用于基本上实现 static_if ,不具有高度争议的条件声明特征。我不是 static_if 的支持者,但有那个。

  template<类型名称t> 
void f(tq){
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<<消息< < is_big<< '\\\
';
}


解决方案

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



如果将此功能添加到C ++中,则应完全指定它,包括与现有C ++功能的所有交互,其中没有设计 _Generic 。例如。 typeid 在C中不存在,但应该在C ++中工作。你可以使用 _Generic 表达式作为 constexpr 吗?作为模板参数?是 lvalue 吗?你可以把它的地址并分配给一个函数指针,并获得重载分辨率?你能做模板参数扣除吗?你可以用 auto 吗? etc。



另一个复杂因素是 _Generic 的主要用例是用于宏的, C ++命名空间。来自 tgmath acos 示例是一个明显的例子。 C ++已经禁止C的标准宏,并要求它们是函数,但是不能使用 tgmath.h


I seem to recall hearing vague comments from a few reliable sources (i.e. committee members speaking in non-official channels) that C type-generic expressions will not be added to C++ because they cannot be.

As far as I can tell, type-generic expressions are very limited compared to C++ templates and overloading, but there is no potential for interaction that would need to be defined as a special case.

A type-generic expression consists of a controlling expression, and a series of "associations" between types and subexpressions. A subexpression is chosen based on the static type of the controlling expression and the types listed for the subexpressions, and it is substituted in place of the TGE. Matching is based on the C concept of type compatibility, which as far as I can tell is equivalent to C++ identity of types with extern linkage under the one-definition rule (ODR).

It would be nice if a derived class controlling expression would select a base class association in C++, but since C doesn't have inheritance, such nicety isn't needed for cross-compatibility. Is this considered to be a stumbling block anyway?

Edit: As for more specific details, C11 already provides for preserving the value category (lvalue-ness) of the chosen subexpression, and seems to require that the TGE is a constant expression (of whatever category) as long as all its operands are, including the controlling expression. This is probably a C language defect. In any case, C++14 defines constant expressions in terms of what may be potentially evaluated, and the TGE spec already says that non-chosen subexpressions are unevaluated.

The point is that the TGE principle of operation seems simple enough to be transplanted without ever causing trouble later.

As for why C++ TGE's would be useful, aside from maximizing the intersection of C and C++, they could be used to essentially implement static_if, sans the highly controversial conditional declaration feature. I'm not a proponent of static_if, but "there is that."

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';
}

解决方案

"Cannot be" is perhaps too strong. "Uncertain whether it's possible" is more likely.

If this feature were to be added to C++, it should be fully specified including all interactions with existing C++ features, many of which were not designed with _Generic in mind. E.g. typeid doesn't exist in C, but should work in C++. Can you use a _Generic expression as a constexpr? As a template parameter? Is it an lvalue ? Can you take its address and assign that to a function pointer, and get overload resolution? Can you do template argument deduction? Can you use it with auto? Etc.

Another complication is that the primary usecase for _Generic is for macro's, which don't play nice with C++ namespaces. The acos example from tgmath is a clear example. C++ already banned C's standard macro's and required them to be functions, but that won't work with tgmath.h.

这篇关于为什么C类型泛型表达式不能与C ++兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆