zoukankan      html  css  js  c++  java
  • C++11中using语法解析及用法

    一、using的所有语法功能

    using这个关键字当然不是在C++11中添加的,但的确是在C++11中扩展了这个关键字的意义,其中最关键的扩展就是增加alias这种语法意义。直接查看gcc的代码,可以清晰的看到using关键字的所有用法及意义。在gcc-4.9.0gcccpparser.c文件的cp_parser_block_declaration函数中,即使通过注释也可以看到这个关键字的主要功能分为三种:using-declaration, a using-directive, or an alias-declaration。三种语法的解析也比较直观:如果using后面直接跟着namespace关键字,则是一个directive;如果下一个是一个变量名并且第三个token是等号则认为是一种类型别名,否则落入第三种using声明。
    static void
    cp_parser_block_declaration (cp_parser *parser,
    bool statement_p)
    {
    ……
    /* If the next keyword is `using', we have a
    using-declaration, a using-directive, or an alias-declaration. */
    else if (token1->keyword == RID_USING)
    {
    cp_token *token2;

    if (statement_p)
    cp_parser_commit_to_tentative_parse (parser);
    /* If the token after `using' is `namespace', then we have a
    using-directive. */
    token2 = cp_lexer_peek_nth_token (parser->lexer, 2);
    if (token2->keyword == RID_NAMESPACE)
    cp_parser_using_directive (parser);
    /* If the second token after 'using' is '=', then we have an
    alias-declaration. */
    else if (cxx_dialect >= cxx11
    && token2->type == CPP_NAME
    && ((cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_EQ)
    || (cp_nth_tokens_can_be_attribute_p (parser, 3))))
    cp_parser_alias_declaration (parser);
    /* Otherwise, it's a using-declaration. */
    else
    cp_parser_using_declaration (parser,
    /*access_declaration_p=*/false);
    }
    ……
    }

    二、using declaration的解析及意义

    同样在不纠结细节的情况下,这里解析的方法就是首先解析所有的作用域(使用"::"表示),直到剩余最后一个identifier,这个identifier将会作为使用整个作用域的一个handle,其实从另一个角度看一认为是一个alias,或者是文件系统中的“链接”:因为本质上是通过一个较短的identifier名称来指代一个更长更完整的变量名。
    gcc-4.9.0gcccpparser.c
    static bool
    cp_parser_using_declaration (cp_parser* parser,
    bool access_declaration_p)
    {
    ……
    qscope = cp_parser_nested_name_specifier (parser, typename_p,
    /*check_dependency_p=*/true,
    /*type_p=*/false,
    /*is_declaration=*/true);
    ……
    /* Parse the unqualified-id. */
    identifier = cp_parser_unqualified_id (parser,
    /*template_keyword_p=*/false,
    /*check_dependency_p=*/true,
    /*declarator_p=*/true,
    /*optional_p=*/false);
    ……
    do_local_using_decl (decl, qscope, identifier);
    else
    do_toplevel_using_decl (decl, qscope, identifier);
    ……
    }
    大家应该都知道在子类中使用using可以引入父类的函数从而绕开“名字隐藏”(name hiding),但是从这个语法解析上看,它还有一个避免歧义的作用,例如下面的例子,如果没有D中的using声明,在main函数中直接使用d.x会有语法错误
    tsecer@harry: cat using.base.var.cpp
    struct B
    {
    int x;
    };
    struct B1
    {
    int x;
    };

    struct D: public B, B1
    {
    using B::x;
    };

    int main()
    {
    D d;
    return d.x;
    }
    tsecer@harry: gcc -std=c++11 using.base.var.cpp
    tsecer@harry:

    三、using作为别名机制

    如果第三个字符是“=”那么此时作为别名机制来解析。从实现上看,这个更像是一个语法糖结构,也就是把通过using形式定义的类型变量转换为“类型+变量”的声明结构。
    static tree
    cp_parser_alias_declaration (cp_parser* parser)
    {
    ……
    id = cp_parser_identifier (parser);
    ……
    type = cp_parser_type_id (parser);
    ……
    declarator = make_id_declarator (NULL_TREE, id, sfk_none);
    declarator->id_loc = id_location;

    member_p = at_class_scope_p ();
    if (member_p)
    decl = grokfield (declarator, &decl_specs, NULL_TREE, false,
    NULL_TREE, attributes);
    else
    decl = start_decl (declarator, &decl_specs, 0,
    attributes, NULL_TREE, &pushed_scope);
    ……
    }

  • 相关阅读:
    第二周:Python3的内存管理
    第一周:JDBC中批量插入数据问题
    PyTorch对ResNet网络的实现解析
    三素数定理的证明及其方法(二)
    三素数定理的证明及其方法(一)
    羊车门问题
    对python语言学习的期待
    My first page
    windowns右键notepad++ 打开文件
    Idea里新建类的快捷键
  • 原文地址:https://www.cnblogs.com/tsecer/p/13668513.html
Copyright © 2011-2022 走看看