C++0x,编译器挂钩和硬编码语言功能

发布于 2024-08-13 21:57:14 字数 1535 浏览 6 评论 0原文

我对C++0x的一些新特性有点好奇。特别是 基于范围的 for 循环< strong>初始化列表。这两个功能都需要用户定义的类才能正常运行。

我看到这篇文章,而顶部- 答案很有帮助。我不知道这是否完全正确(我可能只是完全误解,请参阅第一个答案的第三条评论)。根据当前规范初始化列表,标头定义了一种类型:

template<class E> class initializer_list {
public:
    initializer_list();

    size_t size() const; // number of elements
    const E* begin() const; // first element
    const E* end() const; // one past the last element
};

您可以在规范中看到这一点,只需 Ctrl + F 'classinitializer_list'

为了将 = {1,2,3} 隐式转换为 initializer_list 类,编译器必须了解 {} 之间的关系initializer_list。没有接收任何内容的构造函数,因此据我所知,initializer_list 是一个包装器,它绑定到编译器实际生成的任何内容。

这与 for( : ) 循环相同,它也需要用户定义的类型才能工作(尽管根据规范,更新为不需要数组和初始化列表的任何代码。但是初始化列表require ,因此这是代理的用户定义代码要求)。

我完全误解了这是如何运作的吗?我认为这些新功能实际上极度依赖用户代码,这一点并没有错。感觉好像这些功能是半生不熟的,并且不是将整个功能构建到编译器中,而是一半由编译器完成,一半在包含中完成。这是什么原因呢?

编辑:我输入了“严重依赖编译器代码”,而不是“严重依赖用户代码”。我认为这完全摆脱了我的问题。我的困惑不在于编译器中内置的新功能,而在于编译器中内置的依赖于用户代码的东西。

I'm a little curious about some of the new features of C++0x. In particular range-based for loops and initializer lists. Both features require a user-defined class in order to function correctly.

I came accross this post, and while the top-answer was helpful. I don't know if it's entirely correct (I'm probably just completely misunderstanding, see 3rd comment on first answer). According to the current specifications for initializer lists, the header defines one type:

template<class E> class initializer_list {
public:
    initializer_list();

    size_t size() const; // number of elements
    const E* begin() const; // first element
    const E* end() const; // one past the last element
};

You can see this in the specifications, just Ctrl + F 'class initializer_list'.

In order for = {1,2,3} to be implicitly casted into the initializer_list class, the compiler HAS to have some knowledge of the relationship between {} and initializer_list. There is no constructor that receives anything, so the initializer_list as far as I can tell is a wrapper that gets bound to whatever the compiler is actually generating.

It's the same with the for( : ) loop, which also requires a user-defined type to work (though according to the specs, updated to not require any code for arrays and initializer lists. But initializer lists require <initializer_list>, so it's a user-defined code requirement by proxy).

Am I misunderstanding completely how this works here? I'm not wrong in thinking that these new features do infact rely extremely heavily on user code. It feels as if the features are half-baked, and instead of building the entire feature into the compiler, it's being half-done by the compiler and half done in includes. What's the reason for this?

Edit: I typed 'rely heavily on compiler code', and not 'rely heavily on user code'. Which I think completely threw off my question. My confusion isn't about new features being built into the compiler, it's things that are built into the compiler that rely on user code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

满意归宿 2024-08-20 21:57:14

我认为这些新功能实际上极度依赖编译器代码,这一点并没有错

它们确实极度依赖编译器。无论您是否需要包含标头,事实是在这两种情况下,语法对于当今的编译器来说都是一个解析错误。 for (:) 不太符合当今的标准,唯一允许的结构是 for(;;)

感觉好像这些功能是半生不熟的,并且不是将整个功能构建到编译器中,而是一半由编译器完成,一半在包含中完成。这是什么原因?

该支持必须在编译器中实现,但您需要包含系统的标头才能使其工作。这可以有几个目的,在初始化列表的情况下,它将类型(编译器支持的接口)带入用户的范围,以便您可以有一种使用它的方法(想想 va_args 在 C 中的情况)。对于基于范围的 for(这只是语法糖),您需要将 Range 纳入范围,以便编译器可以执行它的魔力。请注意,标准将 for ( for-range-declaration : expression ) 语句定义为等同于 (草案中的[6.5.4]/1):

{ 
   auto && __range = ( expression ); 
   for ( auto __begin = std::Range<_RangeT>::begin(__range), 
         __end = std::Range<_RangeT>::end(__range); 
         __begin != __end; 
         ++__begin ) { 
      for-range-declaration = *__begin; 
      statement 
   } 
} 

如果您只想在数组和 STL 上使用它可以在没有 Range 概念的情况下实现的容器(不是 C++0x 意义上的),但如果您想将语法扩展到用户定义的类(您自己的容器),编译器可以轻松依赖现有的 Range 模板(具有您自己可能的专业化)。依赖于定义的模板的机制相当于需要容器上的静态接口。

大多数其他语言都朝着需要常规接口(例如容器,...)并在其上使用运行时多态性的方向发展。如果要在 C++ 中完成此操作,则整个 STL 将必须进行重大重构,因为 STL 容器不共享公共基础或接口,并且它们不准备用于多态性。

如果有的话,当前的标准在发布时也不会未成熟

I'm not wrong in thinking that these new features do infact rely extremely heavily on compiler code

They do rely extremely on the compiler. Whether you need to include a header or not, the fact is that in both cases, the syntax would be a parsing error with today compilers. The for (:) does not quite fit into todays standard, where the only allowed construct is for(;;)

It feels as if the features are half-baked, and instead of building the entire feature into the compiler, it's being half-done by the compiler and half done in includes. What's the reason for this?

The support must be implemented in the compiler, but you are required to include a system's header for it to work. This can serve a couple of purposes, in the case of initialization lists, it brings the type (interface to the compiler support) into scope for the user so that you can have a way of using it (think how va_args are in C). In the case of the range-based for (which is just syntactic sugar) you need to bring Range into scope so that the compiler can perform it's magic. Note that the standard defines for ( for-range-declaration : expression ) statement as equivalent to ([6.5.4]/1 in the draft):

{ 
   auto && __range = ( expression ); 
   for ( auto __begin = std::Range<_RangeT>::begin(__range), 
         __end = std::Range<_RangeT>::end(__range); 
         __begin != __end; 
         ++__begin ) { 
      for-range-declaration = *__begin; 
      statement 
   } 
} 

If you want to use it only on arrays and STL containers that could be implemented without the Range concept (not in the C++0x sense), but if you want to extend the syntax into user defined classes (your own containers) the compiler can easily depend upon the existing Range template (with your own possible specialization). The mechanism of depending upon a template being defined is equivalent to requiring a static interface on the container.

Most other languages have gone in the direction of requiring a regular interface (say Container,...) and using runtime polymorphism on that. If that was to be done in C++, the whole STL would have to go through a major refactoring as STL containers do not share a common base or interface, and they are not prepared to be used polimorphically.

If any, the current standard will not be underbaked by the time it goes out.

救星 2024-08-20 21:57:14

这只是语法糖。编译器会将给定的语法结构扩展为直接引用标准类型/符号名称的等效 C++ 表达式。

这并不是现代 C++ 编译器的语言与“外部世界”之间唯一的强耦合。例如,extern "C" 是一种适应 C 链接模型的语言黑客。面向语言的声明线程本地存储的方法隐式依赖于许多 RTL hackery 的工作。

或者看看 C。如何访问通过 ... 传递的参数?需要依赖标准库;但这使用的魔法非常依赖于 C 编译器如何准确地布置堆栈帧。

更新:

如果有什么不同的话,C++ 在这里采取的方法比替代方案更符合 C++ 的精神 - 这将添加一个内在集合或范围类型,烘焙在到语言。相反,它是通过供应商定义的范围类型来完成的。我真的不认为它与可变参数有什么不同,如果没有供应商定义的访问器宏,可变参数同样毫无用处。

It's just syntax sugar. The compiler will expand the given syntactic constructs into equivalent C++ expressions that reference the standard types / symbol names directly.

This isn't the only strong coupling that modern C++ compilers have between their language and the "outside world". For example, extern "C" is a bit of a language hack to accommodate C's linking model. Language-oriented ways of declaring thread-local storage implicitly depend on lots of RTL hackery to work.

Or look at C. How do you access arguments passed via ...? You need to rely on the standard library; but that uses magic that has a very hard dependency on how exactly the C compiler lays out stack frames.

UPDATE:

If anything, the approach C++ has taken here is more in the spirit of C++ than the alternative - which would be to add an intrinsic collection or range type, baked in to the language. Instead, it's being done via a vendor-defined range type. I really don't see it as much different to variadic arguments, which are similarly useless without the vendor-defined accessor macros.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文