zoukankan      html  css  js  c++  java
  • c++新特性实验(1)预处理

    1.参考资料

    1.1 C++

    1.2 gcc对C++的支持

    • gcc官网:         

        https://gcc.gnu.org/

    • gcc 各版本对c++新特性的支持情况 : 

        https://gcc.gnu.org/projects/cxx-status.html

    2.__has_include(C++17 起)

    2.1 作用

        预编译函数. 结果仅表明指定名称的头或源文件 是否存在,并不是已经include过了的意思。 

    2.2 语法

      __has_include ( " 文件名 " )
      __has_include ( < 文件名 > )(C++17 起)

    2.3 示例

        has_inclue.cpp

     1 //#include "has_include.h"
     2 
     3 #if __has_include("has_include.h")
     4     #define NUM 1
     5 #else
     6     #define NUM 0   
     7 #endif
     8 
     9 #include <stdio.h>
    10 #include <stdlib.h>
    11 
    12 
    13 int main(int arg,char *argv[])
    14 {
    15     printf("num = %d
    ",NUM);
    16     return 0;
    17 }
    • 第1行,只要在相应的目录中存在has_include.h文件,就返回true,与第1行的注释打开没有关系.删掉has_include.h后,NUM才是0.
    • 程序在编译完成之后结果就已经确定,运行时动态删除,增加其参数中指定的文件,不会改变结果.

    3.__has_cpp_attribute(C++20 起)

    3.1 作用

    检测标准属性是否存在,检测不了厂商自定义的属性.

    attribute-token 属性 标准
    assert [[assert]] 201806L (C++20)
    carries_dependency [[carries_dependency]] 200809L (C++11)
    deprecated [[deprecated]] 201309L (C++14)
    ensures [[ensures]] 201806L (C++20)
    expects [[expects]] 201806L (C++20)
    fallthrough [[fallthrough]] 201603L (C++17)
    likely [[likely]] 201803L (C++20)
    maybe_unused [[maybe_unused]] 201603L (C++17)
    no_unique_address [[no_unique_address]] 201803L (C++20)
    nodiscard [[nodiscard]] 201603L (C++17)
    noreturn [[noreturn]] 200809L (C++11)
    unlikely [[unlikely]] 201803L (C++20)

    3.2 示例

    1 #if __has_cpp_attribute                        // 检查 __has_cpp_attribute 是否存在
    2 #  if __has_cpp_attribute(deprecated)           // 检查一个属性
    3 #    define DEPRECATED(msg) [[deprecated(msg)]]
    4 #  endif
    5 #endif
    6 #ifndef DEPRECATED
    7 #    define DEPRECATED(msg)
    8 #endif 

    4.#line 增大最大行号值(C++11 )

    4.1 作用

      更改预处理器中的当前行号和文件名。

    4.2 语法

    #line 行号
    或者 #line 行号 "文件名"
    • 行号必须是至少有一个十进制位的序列,并且始终按十进制解释(即使它以 0 开始也是如此)。
    • 行号 为 0 或大于 32767 (C++11 前).则行为未定义,C++11 起最大改为 2147483647 .

    4.3 示例

    1 #include <cassert>
    2 
    3 #define FILENAME "line.cpp"
    4 
    5 int main(int argc, char *argv[]) {
    6    #line 167 FILENAME
    7     assert(1 + 3 == 5);
    8   printf("file = %s,line = %d ",__FILE__,__LINE__);
    9 return 0; 10}

    5.#define 可变参数(C++11)

    5.1 语法

    #define 标识符( 形参, ... ) 替换列表(可选)    (3)    (C++11 起)
    #define 标识符( ... )      替换列表(可选)    (4)    (C++11 起)
    • 实参数量必须多于 (C++20 前)形参数量.C++20起改为不少于 .
    • 替换列表 可以含有记号序列“__VA_OPT__ ( 内容 )”,若 __VA_ARGS__ 非空,则它会被 内容 替换,否则不展开成任何内容。

    5.2 作用

    • #define 指令的版本 (3) 定义有可变数量实参的仿函数宏。额外的实参可用 __VA_ARGS__ 标识符访问,它会被与要被替换的标识符一起提供的实参替换。
    • #define 指令的版本 (4) 定义有可变数量实参的仿函数宏,但无常规实参。额外的实参只能用 __VA_ARGS__ 标识符访问,它会被与要被替换的标识符一起提供的实参替换。

    5.3 示例 

     1 #include <cstdlib>
     2 #include <cstdio>
     3 #include <cstdarg>
     4 
     5 void 
     6 fun(int count,...){
     7     va_list va;
     8 
     9     va_start(va,count);
    10 
    11     for(int i = 0 ; i < count; ++i){
    12         int arg = va_arg(va,int);
    13         printf("arg[%d] = %d , ",i,arg);
    14     }
    15 
    16     va_end(va);
    17 }
    18 
    19 #define TYPE int
    20 #define F(...) fun(0 __VA_OPT__(,) __VA_ARGS__)
    21 #define G(X, ...) fun(0, X __VA_OPT__(,) __VA_ARGS__)
    22 #define SDEF(sname, ...) TYPE sname __VA_OPT__([]= { __VA_ARGS__ })
    23 
    24 
    25 int main(int argc,char *argv[]){
    26     int a = 10,b = 11,c = 12;
    27    
    28     F(a, b, c);             // 替换为 fun(0, a, b, c)
    29     F();                    // 替换为 fun(0)
    30     G(a, b, c);             // 替换为 fun(0, a, b, c)
    31     G(a, );                 // 替换为 fun(0, a)
    32     G(a);                   // 替换为 fun(0, a)
    33     SDEF(foo);              // 替换为 int foo;
    34     SDEF(bar, 1, 2,3,4);    // 替换为 int bar[] = { 1,2,3,4 };
    35 
    36     return 0;
    37 }

     

     1 #include <valarray>
     2 #include <cstdio>
     3 #include <cstdlib>
     4 
     5 
     6 int main(int argc,char *argv[]){
     7 
     8     #define showlist(...) puts(#__VA_ARGS__)
     9 
    10     showlist();            // 展开成 puts("")
    11     showlist(1, "x", int); // 展开成 puts("1, "x", int")
    12 
    13     return 0;
    14 }

     

    1 #define LOGE(TAG,...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
    2 
    3 #define LOGW(TAG,...) __android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__)
    4 
    5 #define LOGD(TAG,...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)
    6 
    7 #define LOGI(TAG,...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) 

     

    6.新增预定义宏(C++11)

    6.1 新增列表

    __STDC_HOSTED__  
    C++11
    若实现有宿主(运行在 OS 下)则展开成整数常量 1,不随 OS 运行则展开成 0​
    __STDCPP_DEFAULT_NEW_ALIGNMENT__  
    C++17

    展开成 std::size_t 字面量,其值为对不具对齐的 operator new 的调用所保证的对齐

    (较大的对齐将传递给具对齐重载,如 operator new(std::size_tstd::align_val_t)) 

    __STDC_VERSION__ C++11 若存在则为实现定义值
    __STDC_ISO_10646__ C++11 若 wchar_t 使用 Unicode ,则展开成 yyyymmL 形式的整数常量,日期指示所支持的 Unicode 的最近版本
    __STDC_MB_MIGHT_NEQ_WC__ C++11

    若对于基本字符集成员 'x' == L'x' 可能为假,则展开成 1,如在基于 EBCDIC 并且

    为 wchar_t 的系统上。 

    __STDCPP_STRICT_POINTER_SAFETY__ C++11 若实现支持严格的 std::pointer_safety 则展开成 1
    __STDCPP_THREADS__ C++11 若程序能拥有多于一个执行线程则展开成 1

     6.2 示例

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <thread>
     4 
     5 
     6 int main(int argc,char *argv[]){
     7 
     8     printf("__STDC_HOSTED__   = %s
    ",__STDC_HOSTED__  );
     9     printf("__STDCPP_DEFAULT_NEW_ALIGNMENT__   = %s
    ",__STDCPP_DEFAULT_NEW_ALIGNMENT__  );
    10     printf("__STDC_VERSION__   = %s
    ",__STDC_VERSION__  );
    11     printf("__STDC_ISO_10646__   = %s
    ",__STDC_ISO_10646__  );
    12     printf("__STDC_MB_MIGHT_NEQ_WC__   = %s
    ",__STDC_MB_MIGHT_NEQ_WC__);
    13     printf("__STDCPP_STRICT_POINTER_SAFETY__   = %s
    ",__STDCPP_STRICT_POINTER_SAFETY__);
    14     printf("__STDCPP_THREADS__   = %s
    ",__STDCPP_THREADS__);
    15 
    16     return 0;
    17 }

    7.__func__(C++11)

    7.1 特殊的函数局域预定义变量

      C++11 起,在每个函数体的作用域内部,都有一个名为 __func__ 的特殊的函数局域预定义变量,定义为一个持有具有实现定义格式的函数名的静态字符数组。

      它不是预处理器宏.

    7.2 示例

     1 int main(int argc,char *argv[]){
     2 
     3     printf("__DATE__ = %s 
     ",__DATE__);
     4     printf("__TIME__ = %s 
     ",__TIME__);
     5     printf("__FILE__ = %s 
     ",__FILE__);
     6     printf("__LINE__ = %d 
     ",__LINE__);
     7     printf("__FUNCTION__ = %s 
     ",__FUNCTION__);
     8     printf("__func__ = %s 
     ",__func__);
     9 
    10     return 0;
    11 }

     

  • 相关阅读:
    git 每次push和pull都需要提交密码
    git push时报错refusing to merge unrelated histories
    打包时,node内存溢出问题解决方法
    dva中roadhog版本升级后带来的问题及解决方法
    Android
    Python Model : glob 文件路径查找
    Tools info
    Python class
    Life Info
    Char 10 格式化及如何正确使用
  • 原文地址:https://www.cnblogs.com/mhbs/p/10556015.html
Copyright © 2011-2022 走看看