我正在尝试为日志记录机制编写宏。 我编写了一个可变参数宏,但它不适用于std::string。 该代码如下所示:

#include

#include

#define LOG_NOTE(m, ...) printf(m, ##__VA_ARGS__)

int main()

{

std::string foo ="random string";

int bar = 5;

LOG_NOTE("%s %d %s","Hello World", bar, foo);

return 0;

}

如果我像下面这样调用宏,则不会出现任何错误。

LOG_NOTE("%s %d %s","Hello World", bar,"random string");

编译器输出:

In function 'int main()': 5:49: error: cannot pass objects of

non-trivially-copyable type 'std::string {aka class

std::basic_string}' through '...' 11:5: note: in expansion of

macro 'LOG_NOTE'

顺便说一句,如果您使用gcc的-E标志来获取预处理器之后的输出,则在编写宏时会很有帮助。

您是否需要格式,还是只是用空格分隔的值?

我实际上只需要用空格分隔的值,目前我正在尝试根据答案实施它,但是我收到了链接器错误

您不能将对象传递给printf,因此当前必须使用

LOG_NOTE("%s %d %s","Hello World", bar, foo.c_str());

如果您不需要格式化,只需将每个参数都用空格隔开,则可以简单地使用可变参数模板而不是MACRO:

template

void LOG_NOTE(const Ts&...args)

{

const char* sep ="";

(((std::cout << sep << args), sep =""), ...); // C++17 folding expression

// C++11/C++14 version are more verbose:

// int dummy[] = {0, ((std::cout << sep << args), (sep =""), 0)...};

// static_cast(dummy); // avoid warning for unused variable

}

int main()

{

std::string foo ="random string";

int bar = 5;

LOG_NOTE("Hello World", bar, foo);

}

演示版

感谢您的输入@ Jarod42,但我已经为C ++ 17找到了类似的答案。但是,我正在寻找头和源文件分开的C ++ 11示例。

template不是在头文件和cpp文件之间拆分的最佳选择。

添加了C ++ 11版本。

这里的问题不是可变参数宏,而是对printf的调用。 看一下文档:格式说明符"%s"对应于char*,而不是std::string。 printf仅能处理原始的内置类型。 您可以将调用更改为

LOG_NOTE("%s %d %s","Hello World", bar, foo.c_str());

解决这个问题。

或者,使用增强格式。它确实支持std::string和许多其他用户定义的类型。

I wrote a variadic macro

别。 使用可变参数模板函数。

您遇到的实际问题是,您试图通过C API(printf)传递C ++对象(std::string)。 这是不可能的。

您需要某种转换机制,例如:

#include

#include

template

decltype(auto) convert_for_log_note(T const& x)

{

return x;

}

decltype(auto) convert_for_log_note(std::string const& x)

{

return x.c_str();

}

template

void LOG_NOTE(const char* format, Args&&...args)

{

printf(format, convert_for_log_note(args)...);

}

int main()

{

std::string foo ="random string";

int bar = 5;

LOG_NOTE("%s %d %s

","Hello World", bar, foo);

return 0;

}

输出示例:

Hello World 5 random string

http://coliru.stacked-crooked.com/a/beb3431114833860

公平地说,日志宏是众所周知的"无宏"规则的免除项,原因有以下三个:__FILE__,__LINE__以及在发行版本中将其转换为"不执行"语句的能力。您不能消除函数调用参数的副作用。

只要C ++委员会能够表现自己,@ MSalters很快就会拥有std :: source_location,它将与if constexpr一起完全消除对宏的需求。请注意,只要您通过通用引用传递参数,参数的副作用就不会成为问题。显然传递LOG("%s%",mything.to_string()。c_str());确实会带来副作用,因此应避免使用。最好为convert_for_log_note(MyThing const&)类型提供ADL重载。

c语言宏不能传递参数,关于c ++:可变参数宏:不能通过’…’传递非平凡复制类型的对象...相关推荐

  1. #{}不自动改参数类型_【Just For Fun】C - 可变参数函数、可变参数宏 __VA_ARGS__、额外的逗号

    [Just For Fun] 本系列纯粹娱乐.研究用.一些旁门左道的东西. 事实上可能完全没用. (๑•̀ω•́๑) 對於可变参数函数.可变参数宏 __VA_ARGS__ , 我曾經有在另一些地方寫過 ...

  2. Python学习之路:函数传递可变参数与不可变参数

    函数传参的方法: 太基础了,8说了 直接上重点 一.可变参数的传递 可变参数有:列表.集合.字典 直接上代码: a = [1, 2]def fun(a):print('传入函数时a的值为:', a)a ...

  3. Kotlin传递可变长参数给Java可变参数方法

    定义Java可变参数方法 package com.tcl.john.studymvvm.utils;/*** 调用Java方法的工具类* Created by ZhangJun on 2017/10/ ...

  4. python 默认参数后接可变参数_Python可变参数会自动填充前面的默认同名参数实例...

    Python可变参数会自动填充前面的默认同名参数实例 最近在学习Python的时候遇到一个知识点,在此记录下来 可变参数会自动填充前面的同名默认参数 比如下面这个函数 def add_student( ...

  5. python中可变参数args传入函数时储存的类型是_[转载]Python中函数的参数定义和可变参数*args与**args...

    Python中函数的参数定义和可变参数 *args与**args区别 刚学用Python的时候,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和** ...

  6. python中可变参数和关键字参数_python的可变参数和关键字参数(*args **kw)

    本文是来自廖大的python教程其中我一直忘记的部分.算是一个笔记把.因为日常这俩参数名字一直搞混 可变参数 在Python函数中,还可以定义可变参数.顾名思义,可变参数就是传入的参数个数是可变的,可 ...

  7. c 语言 宏 可变 参数,利用C可变参数和宏定义来实现自己的日志系统

    在嵌入式应用的开发过程中,日志系统是非常重要的! 特别是在生产环节出现了偶发性的.与当前的执行环境相关的bug的时候, 如果没有日志系统来追踪问题,很难进行问题重现. 因此,实现一个自己的日志系统是很 ...

  8. C# 编程入门第七课方法调用参数问题,方法标准,传递数组,返回数组,方法高级参数(out关键字参数,ref参数,params可变参数),方法重载,方法的递归,一些常用方法

    C# 编程入门第七课 文章目录 C# 编程入门第七课 1. 方法调用参数问题 2. 方法标准 3.传递数组,返回数组 4. 方法高级参数 4.1 out 关键字参数 4.2 ref 参数 4.3 pa ...

  9. Python中函数的参数定义和可变参数

    刚学用Python的时候,特别是看一些库的源码时,经常会看到func(*args, **kwargs)这样的函数定义,这个*和**让人有点费解.其实只要把函数参数定义搞清楚了,就不难理解了. 先说说函 ...

最新文章

  1. html5表单验证没有效果,HTML5表单验证特性(知识点小结)
  2. MySQL在创建索引之前一定要想到的事情
  3. 对于初学者十条PCB元器件摆放小技巧
  4. oracle 查看锁表进程和解锁
  5. 2017,SAP向云看齐
  6. shell输出没有换行符
  7. vue监听路由的变化,跳转到同一个页面时,Url改变但视图未重新加载问题
  8. 2019-12-11 转载TCP/IP编程常用C语言头文件
  9. WordPress 插件漏洞被利用,近 20 万站点还没打补丁
  10. 【代码】求二叉树叶子结点的个数、递归方式
  11. 如何把网站程序文件快速上传到服务器空间经历分享
  12. 影片下载观看秘籍大全
  13. TX2--Building OpenCV for Tegra with CUDA
  14. comsol如何定义狄利克雷边界_COMSOL中周期性边界条件的应用
  15. 计算机对康复治疗学的帮助,我院康复医学科引进认知训练配合计算机心理失语症脑功能评估训练系统...
  16. hdu3018解题报告--也是白话几笔画学习总结
  17. 海南计算机报名系统入口湖南,海南全国教师管理信息系统自助子系统登录入口...
  18. 【分享】中毒后360安全卫士打不开的终极解决办法
  19. 使用css制作永动的动画
  20. 数百亿次暴力破解和网络钓鱼攻击被微软去年拦截了

热门文章

  1. QQ音乐听歌升级漏洞-用C实现接口
  2. 百度前端技术学院第19天
  3. c# 读取INI文件(将内容写入INI文件)
  4. 剑指offer----C语言版----第四天
  5. Android Design Support Library BottomSheetBehavior使用
  6. JAVA 格式化英文日期
  7. 网络安全保险的新兴发展与监管研究
  8. AFNetworking上传图片
  9. 打开量化投资黑箱、投资学
  10. Go框架之Beego简介部署及程序流程整合