Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why cannot C type-generic expressions be compatible with C++?

Tags:

c++

c

c11

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';
}
like image 916
Potatoswatter Avatar asked Dec 23 '13 08:12

Potatoswatter


1 Answers

"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.

like image 176
MSalters Avatar answered Oct 26 '22 16:10

MSalters