将变量的名称传递给C ++中的函数

时间:2016-03-18 16:47:49

标签: c++ templates c++11 pretty-print

我正在尝试创建打印功能。我希望它能够获取变量列表并打印出它们的值和名称。到目前为止,我有以下代码:

std::ostream& debug_values(std::ostream& out);  

template <typename V, typename... R>
std::ostream& debug_values(
    std::ostream& out, const V& value, const R&... remaining) {
  out << value << ", ";
  debug_values(out, remaining...);
  return out;
}

这样可行,但它只打印出值。例如:

ostream out;
int i1 = 1;
int i2 = 2;
debug_values(out, i1, i2) //Will print 1, 2

相反,我希望debug_values打印出以下内容:

debug_values(out, i1, i2); //i1: 1, i2: 2

有没有办法在C ++中执行此操作?如果是这样,怎么样?

4 个答案:

答案 0 :(得分:2)

  

有没有办法在C ++中执行此操作?如果是这样,怎么样?

不,你不能这样做,当你把变量作为参数传递时,变量名不会以某种方式保存。

使用普通c ++语言是不可能的,但c-preprocessor可用于创建变量名称的字符串化(请参阅#运算符)版本,并将它们用于调试/日志记录输出

缺点是,你必须创建一个可能的debug_values()宏的版本,它被解析为固定数量的给定参数(尽管IIRC有可用的宏元编程库,支持更容易实现这些东西) )。

答案 1 :(得分:2)

您无法使用纯C ++来实现这一目标。 但是,您可以使用预处理器来实现您想要的功能

#define PP( expr ) std::cout<<#expr<<" "<<expr<<std::endl;

在此处观看:http://ideone.com/UopOni

或者,Qt的QObject可以有这种名为properties的命名变量

此解决方案对于调试或日志记录非常有用,但它不是很漂亮。

答案 2 :(得分:0)

  

有没有办法在C ++中执行此操作?如果是这样,怎么样?

您可以使用std::map

ostream out;
int i1 = 1;
int i2 = 2;
std::map<std::string, int> values;
values["i1"] = i1;
values["i2"] = i2;

// Change debug_values to use the map as its second argument type
debug_values(out, values)

有没有办法自动创建map?我不认为有。

答案 3 :(得分:0)

使用MACRO,您可以

// (up to hard coded 6 arguments)
#define NARGS_(_1, _2, _3, _4, _5 , _6, N, ...) N
#define NARGS(...) NARGS_(__VA_ARGS__, 6, 5, 4, 3, 2, 1)

#define CAT_(a, b) a ## b
#define CAT(a, b) CAT_(a, b)

#define name_1(x)                     #x, x
#define name_2(x, x2)                 #x, x, #x2, x2
#define name_3(x, x2, x3)             #x, x, #x2, x2, #x3, x3
#define name_4(x, x2, x3, x4)         #x, x, #x2, x2, #x3, x3, #x4, x4
#define name_5(x, x2, x3, x4, x5)     #x, x, #x2, x2, #x3, x3, #x4, x4, #x5, x5
#define name_6(x, x2, x3, x4, x5, x6) #x, x, #x2, x2, #x3, x3, #x4, x4, #x5, x5, #x6, x6

#define names(...) CAT(name_, NARGS(__VA_ARGS__))(__VA_ARGS__)
#define debug_values(out, ...) debug_values_impl(out, names(__VA_ARGS__))

std::ostream& debug_values_impl(std::ostream& out) { return out << std::endl; }
template <typename T, typename ... Ts>
std::ostream&
debug_values_impl(std::ostream& out, const char* name, const T& value, const Ts&... args)
{
    out << name << ':' << value << ", ";
    return debug_values_impl(out, args...);
}

Demo