代码之家  ›  专栏  ›  技术社区  ›  Dave

C++0x、编译器钩子和硬编码语言特征

  •  5
  • Dave  · 技术社区  · 15 年前

    我对C++0x的一些新特性有点好奇。 range-based for loops initializer lists . 这两个功能都需要用户定义的类才能正常工作。

    我来了 this post 而最上面的答案是有用的。我不知道这是否完全正确 (我可能只是完全误解了,见第三条关于第一个答案的评论) . 根据 current specifications 对于初始值设定项列表,头定义一种类型:

    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 '类初始值设定项列表' .

    为了 = {1,2,3} 被隐式地投入 initializer_list 类,编译器必须了解 {} 初始值设定项列表 .没有任何构造函数可以接收任何内容,因此,据我所知,初始值设定项列表是一个绑定到编译器实际生成的任何内容的包装器。

    这和 for( : ) 循环,它还需要用户定义的类型才能工作(尽管根据规范,已更新为不需要数组和初始值设定项列表的任何代码)。但初始值设定项列表需要 <initializer_list> ,所以这是一个用户定义的代理代码需求)。

    我完全误解了这里的工作原理吗?我认为这些新特性确实非常依赖于用户代码,这并不是错的。感觉就像功能是半生不熟的,而不是将整个功能构建到编译器中,而是由编译器完成一半,在include中完成一半。为什么会这样?

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

    2 回复  |  直到 15 年前
        1
  •  3
  •   David Rodríguez - dribeas    15 年前

    我认为这些新特性确实非常依赖于编译器代码,这是正确的。

    它们确实非常依赖编译器。无论您是否需要包含一个头部,事实是在这两种情况下,语法在今天的编译器中都是一个解析错误。这个 for (:) 不完全符合今天的标准,其中唯一允许的构造是 for(;;)

    感觉就像功能是半生不熟的,而不是将整个功能构建到编译器中,而是由编译器完成一半,在include中完成一半。为什么会这样?

    支持必须在编译器中实现,但需要包含系统的头文件才能工作。这有两个用途,在初始化列表的情况下,它将类型(编译器支持的接口)引入到用户的作用域中,这样您就可以有一种使用它的方法(想想在C中va参数是如何使用的)。在基于范围的情况下(这只是语法上的糖分),您需要将范围纳入范围,以便编译器能够执行它的魔力。请注意,该标准定义了 for ( for-range-declaration : expression ) statement 相当于(草案中的[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 
       } 
    } 
    

    如果您只想在没有 Range 概念(不在C++ 0x意义下),但是如果要将语法扩展到用户定义的类(您自己的容器),编译器可以很容易地依赖现有的。 范围 模板(具有您自己可能的专业化)。依赖所定义的模板的机制相当于需要容器上的静态接口。

    大多数其他语言已经朝着需要一个常规接口(比如容器…)和使用运行时多态性的方向发展。如果这是在C++中完成的,整个STL将不得不经历一个主要的重构,因为STL容器不共享一个公共的基础或接口,并且它们不准备被使用。

    如果有,当前标准将不会 刹车不足 当它熄灭的时候。

        2
  •  1
  •   Barry Kelly    15 年前

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

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

    或者看C。你如何访问通过 ... ?您需要依赖于标准库;但是这使用了一种魔力,它对C编译器如何精确地布置堆栈帧有着非常困难的依赖性。

    更新:

    如果有的话,c++的方法在这里比C++的更多,它将是一个补充。 内在的 集合或范围类型,烘焙到语言中。相反,它是通过供应商定义的范围类型完成的。我真的不认为它与variadic参数有什么不同,如果没有供应商定义的访问器宏,这些参数同样是无用的。