How to get variable name from template g++ - c++

How can i get/print variable name from this? I am using arduino Stream to print to console.
#ifndef any_h
#define any_h
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
struct any {
any(Stream& s):serial(s){}
template <class T>
void print(const T& msg)
{
getName(class T);
serial.print(msg);
}
template <class A, class... B>
void print(A head, B... tail)
{
print('{');
print(head);
print(tail...);
}
private:
Stream& serial;
};
#endif
Usage:
any A(Serial);
int myInt =34;
float myFloat = 944.5555f;
String myString = " this string";
A.print(myInt,myFloat,myString);
current output
34944.555 this string
I am trying to get something like with the same usage/access or like in this: Demo.
{"variableName":value,"variableName":value}
// That is in this case:
{myInt:34,myFloat:944.55,myString: this string}
What i have already tried:
#define getName(x) serial.print(#x)
void print(const T& msg)
{
getName(msg);
//getName(class T);
serial.print(msg);
}
output : msg34msg944.555msg this string

You can use macro to do that combined with stringify preprocessor:
Code:
#include <stdio.h>
#define PRINT_NAME(name) print_name(#name, (name))
void print_name(char *name, char* value) {
printf("name: %s ---> value: %s\n", name, value);
}
int main (int argc, char* argv[]) {
char* var1 = 'my var 1';
char* var2 = 'my new var 2';
PRINT_NAME(var1);
PRINT_NAME(var2);
return 0;
}
Output:
name: var1 --> value: my var 1
name: var2 --> value: my new var 2
I hope this helps :)

C++ doesn't have reflection, so you're limited to using macros, such as:
#include <iostream>
#define STRINGIFY_IMPL(X) #X
#define STRINGIFY(X) STRINGIFY_IMPL(X)
#define VARIABLE_NAME(X) STRINGIFY(X)
#define VARIABLE_VALUE(X) X
int main()
{
double d = 3.141;
std::cout << VARIABLE_NAME(d) << ": " << VARIABLE_VALUE(d) << '\n';
return 0;
}
(VARIABLE_NAME and VARIABLE_VALUE aren't truly needed, you could also use std::cout << STRINGIFY(d) << ": " << d << '\n';).
You can, of course, combine this all into a super macro (with macros from above):
#include <iostream>
#include <string>
#define STREAM_NAME_VALUE(str, X) str << '{' << STRINGIFY(X) << ':' << X << '}'
int main()
{
int myInt =34;
float myFloat = 944.5555f;
std::string myString = " this string";
STREAM_NAME_VALUE(std::cout, myInt);
std::cout << '\n';
STREAM_NAME_VALUE(std::cout, myFloat);
std::cout << '\n';
STREAM_NAME_VALUE(std::cout, myString);
std::cout << '\n';
return 0;
}

Related

C++ variadic dump macro? [duplicate]

#include <bits/stdc++.h>
using namespace std;
#define __deb(X...) (cout << "[" << #X << "]:" << X)
template <typename... type>
void debug(type &&... args)
{
((__deb(args)), ...);
}
int main()
{
int a = 1, b = 3;
debug(a,b);
return 0;
}
I got output like [args]:1[args]:3
but I wanted output like [a]:1[b]:3
One way could be to quote all the macro arguments using #__VA_ARGS__ and parse that string in the C++ function.
Example:
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
template<typename T, typename... Args>
std::string debug_detail(const char* names, T&& var, Args&&... args) {
std::ostringstream builder;
// find variable end
const char* end = names;
while(*end != ',' && *end != '\0') ++end;
// display one variable
(builder << ' ').write(names, end - names) << '=' << var;
// continue parsing?
if constexpr(sizeof...(Args) > 0) {
// recursively call debug_detail() with the new beginning for names
builder << debug_detail(end + 1, std::forward<Args>(args)...);
}
return builder.str();
}
template<typename... Args>
void debug_entry(const char* file, int line, const char* func,
const char* names, Args&&... args) {
std::ostringstream retval;
// common debug info
retval << file << '(' << line << ") " << func << ':';
// add variable info
retval << debug_detail(names, std::forward<Args>(args)...) << '\n';
std::cout << retval.str();
}
// the actual debug macro
#define debug(...) \
debug_entry(__FILE__,__LINE__,__func__,#__VA_ARGS__,__VA_ARGS__)
int main() {
int foo = 1;
const double bar = 2;
const std::string Hello = "world";
debug(foo,bar,Hello);
}
Possible output:
example.cpp(49) main: foo=1 bar=2 Hello=world
Demo
A C++20 version using std::source_location:
#include <source_location>
template<typename... Args>
void debug_entry(const std::source_location location,
const char* names, Args&&... args) {
std::ostringstream retval;
// common debug info
retval << location.file_name() << '(' << location.line() << ','
<< location.column() << ") " << location.function_name() << ':';
// add variable info
retval << debug_detail(names, std::forward<Args>(args)...) << '\n';
std::cout << retval.str();
}
// the actual debug macro
#define debug(...) \
debug_entry(std::source_location::current(), #__VA_ARGS__,__VA_ARGS__)
Demo
Here's my humble attempt, which uses a macro FOO to create a pair of the variable name and its value, and passes the arguments to a variadic function:
#include <utility>
#include <iostream>
#define FOO(var) std::make_pair(std::string(#var), var)
template <typename T>
void __deb(std::pair<std::string, T> arg) { std::cout << "[" << arg.first << "]:" << arg.second; }
template <typename... type>
void debug(std::pair<std::string, type> &&... args)
{
(__deb(args), ...);
}
int main()
{
int a = 1, b = 3;
debug(FOO(a), FOO(b));
}
Demo
Alternatively, to avoid having a macro call FOO for each variable in debug, you could define debug as a macro that accepts #__VA_ARGS__ (string of arguments) and __VA_ARGS__ (argument values). Then parse each variable name and value:
#include <iostream>
#include <sstream>
#include <stdio.h>
#define debug(...) debug_print(#__VA_ARGS__,__VA_ARGS__)
template <typename T>
void __deb(std::istringstream &ss, T arg)
{
//Extract name from stream
std::string name;
std::getline(ss, name, ',');
//trim leading space
const auto pos(name.find_first_not_of(" "));
name.erase(0, pos);
std::cout << "[" << name << "]:" << arg;
}
template <typename... type>
void debug_print(const char* names, type&&...args)
{
std::istringstream ss(names);
(__deb(ss, args), ...);
}
int main()
{
int a = 1, b = 3, c = 4;
debug(a, b, c);
}
Demo
The problem is that the MACRO is used in the context of void debug(type &&... args), which is not familiar with the names a and b.
A possible solution to your problem is to implement a bigger MACRO which gats several vars and calls a sub-MACRO which handles a single var (which you already implemented).
This way the initial MACRO call will happen in the context of the calling function which has the wanted vars

Stray # in program [duplicate]

#include <bits/stdc++.h>
using namespace std;
#define __deb(X...) (cout << "[" << #X << "]:" << X)
template <typename... type>
void debug(type &&... args)
{
((__deb(args)), ...);
}
int main()
{
int a = 1, b = 3;
debug(a,b);
return 0;
}
I got output like [args]:1[args]:3
but I wanted output like [a]:1[b]:3
One way could be to quote all the macro arguments using #__VA_ARGS__ and parse that string in the C++ function.
Example:
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
template<typename T, typename... Args>
std::string debug_detail(const char* names, T&& var, Args&&... args) {
std::ostringstream builder;
// find variable end
const char* end = names;
while(*end != ',' && *end != '\0') ++end;
// display one variable
(builder << ' ').write(names, end - names) << '=' << var;
// continue parsing?
if constexpr(sizeof...(Args) > 0) {
// recursively call debug_detail() with the new beginning for names
builder << debug_detail(end + 1, std::forward<Args>(args)...);
}
return builder.str();
}
template<typename... Args>
void debug_entry(const char* file, int line, const char* func,
const char* names, Args&&... args) {
std::ostringstream retval;
// common debug info
retval << file << '(' << line << ") " << func << ':';
// add variable info
retval << debug_detail(names, std::forward<Args>(args)...) << '\n';
std::cout << retval.str();
}
// the actual debug macro
#define debug(...) \
debug_entry(__FILE__,__LINE__,__func__,#__VA_ARGS__,__VA_ARGS__)
int main() {
int foo = 1;
const double bar = 2;
const std::string Hello = "world";
debug(foo,bar,Hello);
}
Possible output:
example.cpp(49) main: foo=1 bar=2 Hello=world
Demo
A C++20 version using std::source_location:
#include <source_location>
template<typename... Args>
void debug_entry(const std::source_location location,
const char* names, Args&&... args) {
std::ostringstream retval;
// common debug info
retval << location.file_name() << '(' << location.line() << ','
<< location.column() << ") " << location.function_name() << ':';
// add variable info
retval << debug_detail(names, std::forward<Args>(args)...) << '\n';
std::cout << retval.str();
}
// the actual debug macro
#define debug(...) \
debug_entry(std::source_location::current(), #__VA_ARGS__,__VA_ARGS__)
Demo
Here's my humble attempt, which uses a macro FOO to create a pair of the variable name and its value, and passes the arguments to a variadic function:
#include <utility>
#include <iostream>
#define FOO(var) std::make_pair(std::string(#var), var)
template <typename T>
void __deb(std::pair<std::string, T> arg) { std::cout << "[" << arg.first << "]:" << arg.second; }
template <typename... type>
void debug(std::pair<std::string, type> &&... args)
{
(__deb(args), ...);
}
int main()
{
int a = 1, b = 3;
debug(FOO(a), FOO(b));
}
Demo
Alternatively, to avoid having a macro call FOO for each variable in debug, you could define debug as a macro that accepts #__VA_ARGS__ (string of arguments) and __VA_ARGS__ (argument values). Then parse each variable name and value:
#include <iostream>
#include <sstream>
#include <stdio.h>
#define debug(...) debug_print(#__VA_ARGS__,__VA_ARGS__)
template <typename T>
void __deb(std::istringstream &ss, T arg)
{
//Extract name from stream
std::string name;
std::getline(ss, name, ',');
//trim leading space
const auto pos(name.find_first_not_of(" "));
name.erase(0, pos);
std::cout << "[" << name << "]:" << arg;
}
template <typename... type>
void debug_print(const char* names, type&&...args)
{
std::istringstream ss(names);
(__deb(ss, args), ...);
}
int main()
{
int a = 1, b = 3, c = 4;
debug(a, b, c);
}
Demo
The problem is that the MACRO is used in the context of void debug(type &&... args), which is not familiar with the names a and b.
A possible solution to your problem is to implement a bigger MACRO which gats several vars and calls a sub-MACRO which handles a single var (which you already implemented).
This way the initial MACRO call will happen in the context of the calling function which has the wanted vars

class header: error: expected unqualified-id before 'char' while compiling

Sorry for bad english.
I am new on c++ and trying to understand to send references to class object.
But I get above error. If I use const char then error comes up for 'const' part.
Here is my code:
main:
#include <iostream>
#include "DelMe-ClassHeader.h"
using namespace std;
int main() {
char var1 [2];
int var2;
for (int i = 0; i < 2; i++) {
var1[i] = 2;
}
int var2 = 0;
tc = TestClass(var1, var2);
cout << "before tc.changeValue" << endl;
cout << "var1 is " << var1 << endl;
cout << "var2 is " << var2 << endl;
tc.changeValue()
cout << "before tc.changeValue" << endl;
cout << "var1 is " << var1 << endl;
cout << "var2 is " << var2 << endl;
}
header:
#ifndef TestClass
#define TestClass
#include <iostream>
using namespace std;
class TestClass {
public:
TestClass(char (& first)[2]}, int& second);
void changeValue ();
private:
char (& privArray)[2];
int& privInt;
};
#endif
cpp:
#include "DelMe-ClassHeader.h"
#include <iostream>
using namespace std;
TestClass::TestClass(char (& first)[15], int& second) {
this->priveArray = first;
this->privInt = second;
}
void TestClass::changeValue () {
privInt = atoi(privArray);
}
and the error is:
E:\Programing\CodeBlocks\Cpp\DelMe\DelMe\DelMe-ClassHeader.h|10|error: expected unqualified-id before 'char'
I gratefull for any help
The header contains two errors:
#define TestClass defines TestClass as an empty string. Therefore all occurences of TestClass will be replaced with an empty string, hence the errors. For more information read about the C++ preprocessor.
There is an extra } in the parameter list of TestClass.
Replace with this:
#ifndef TestClass_h_inc_
#define TestClass_h_inc_
#include <iostream>
using namespace std;
class TestClass {
public:
TestClass(char(&first)[2], int& second);
void changeValue();
private:
char(&privArray)[2];
int& privInt;
};
#endif

how to print many variables with there name and their corresponding value in c++?

#include <bits/stdc++.h>
using namespace std;
#define __deb(X...) (cout << "[" << #X << "]:" << X)
template <typename... type>
void debug(type &&... args)
{
((__deb(args)), ...);
}
int main()
{
int a = 1, b = 3;
debug(a,b);
return 0;
}
I got output like [args]:1[args]:3
but I wanted output like [a]:1[b]:3
One way could be to quote all the macro arguments using #__VA_ARGS__ and parse that string in the C++ function.
Example:
#include <iostream>
#include <sstream>
#include <string>
#include <utility>
template<typename T, typename... Args>
std::string debug_detail(const char* names, T&& var, Args&&... args) {
std::ostringstream builder;
// find variable end
const char* end = names;
while(*end != ',' && *end != '\0') ++end;
// display one variable
(builder << ' ').write(names, end - names) << '=' << var;
// continue parsing?
if constexpr(sizeof...(Args) > 0) {
// recursively call debug_detail() with the new beginning for names
builder << debug_detail(end + 1, std::forward<Args>(args)...);
}
return builder.str();
}
template<typename... Args>
void debug_entry(const char* file, int line, const char* func,
const char* names, Args&&... args) {
std::ostringstream retval;
// common debug info
retval << file << '(' << line << ") " << func << ':';
// add variable info
retval << debug_detail(names, std::forward<Args>(args)...) << '\n';
std::cout << retval.str();
}
// the actual debug macro
#define debug(...) \
debug_entry(__FILE__,__LINE__,__func__,#__VA_ARGS__,__VA_ARGS__)
int main() {
int foo = 1;
const double bar = 2;
const std::string Hello = "world";
debug(foo,bar,Hello);
}
Possible output:
example.cpp(49) main: foo=1 bar=2 Hello=world
Demo
A C++20 version using std::source_location:
#include <source_location>
template<typename... Args>
void debug_entry(const std::source_location location,
const char* names, Args&&... args) {
std::ostringstream retval;
// common debug info
retval << location.file_name() << '(' << location.line() << ','
<< location.column() << ") " << location.function_name() << ':';
// add variable info
retval << debug_detail(names, std::forward<Args>(args)...) << '\n';
std::cout << retval.str();
}
// the actual debug macro
#define debug(...) \
debug_entry(std::source_location::current(), #__VA_ARGS__,__VA_ARGS__)
Demo
Here's my humble attempt, which uses a macro FOO to create a pair of the variable name and its value, and passes the arguments to a variadic function:
#include <utility>
#include <iostream>
#define FOO(var) std::make_pair(std::string(#var), var)
template <typename T>
void __deb(std::pair<std::string, T> arg) { std::cout << "[" << arg.first << "]:" << arg.second; }
template <typename... type>
void debug(std::pair<std::string, type> &&... args)
{
(__deb(args), ...);
}
int main()
{
int a = 1, b = 3;
debug(FOO(a), FOO(b));
}
Demo
Alternatively, to avoid having a macro call FOO for each variable in debug, you could define debug as a macro that accepts #__VA_ARGS__ (string of arguments) and __VA_ARGS__ (argument values). Then parse each variable name and value:
#include <iostream>
#include <sstream>
#include <stdio.h>
#define debug(...) debug_print(#__VA_ARGS__,__VA_ARGS__)
template <typename T>
void __deb(std::istringstream &ss, T arg)
{
//Extract name from stream
std::string name;
std::getline(ss, name, ',');
//trim leading space
const auto pos(name.find_first_not_of(" "));
name.erase(0, pos);
std::cout << "[" << name << "]:" << arg;
}
template <typename... type>
void debug_print(const char* names, type&&...args)
{
std::istringstream ss(names);
(__deb(ss, args), ...);
}
int main()
{
int a = 1, b = 3, c = 4;
debug(a, b, c);
}
Demo
The problem is that the MACRO is used in the context of void debug(type &&... args), which is not familiar with the names a and b.
A possible solution to your problem is to implement a bigger MACRO which gats several vars and calls a sub-MACRO which handles a single var (which you already implemented).
This way the initial MACRO call will happen in the context of the calling function which has the wanted vars

Using MACRO for creating strings (e.g. array index) dynamically inside a for loop

I want to dynamically create strings using MACRO. e.g. if I have int i in range of 1:n and string "testArray". I should be able to create testArray[0],testArray[1], ... testarray[n-1]
Please let me know if it is possible.
Below is sample code :
void fun2(int x,std::string name)
{
/*do something*/
}
void fun1()
{
for (unsigned int i = 0 ;i < 5 ; ++i )
{
// I want to create a MACRO such that it create "testArray[0]","testArray[1]",..."testArray[4]" etc.
fun2(x,CREATE_ARRAY_ELEM ("testArray",i));
}
}
I tried below but it does not work :
#define STR1(x) #x
#define CREATE_INDEX(paramName,elementIndex) #paramName << "[" << elementIndex << "]"
#define CREATE_ARRAY_ELEM(paramName,elementIndex) CREATE_INDEX(paramName,elementIndex)
#define STRINGIZE_1(x) STR1(x)
You appear to be wanting to create the string literals "testArray[0]", "testArray[1]", etc.. at compile time. Thats not going to happen. You could easily accomplish this at runtime using an ostringstream, but I don't think that is what you're looking for.
If it is what you're looking for, then...
#include <iostream>
#include <sstream>
using namespace std;
static std::string array_str(const char* s, unsigned int i)
{
std::ostringstream oss;
oss << s << '[' << i << ']';
return oss.str();
}
void fun2(int x, const std::string& name)
{
std::cout << x << ':' << name << std::endl;
}
void fun1()
{
for (unsigned int i = 0 ;i < 5 ; ++i )
{
fun2(i, array_str("testArray", i));
}
}
Test Output
0:testArray[0]
1:testArray[1]
2:testArray[2]
3:testArray[3]
4:testArray[4]
you can do like this..means in macros itself you have to display the desired string ..
#include<iostream>
#define STR1(x) #x
#define CREATE_INDEX(paramName,elementIndex) cout <<paramName<< "[" << elementIndex << "]"
#define CREATE_ARRAY_ELEM(paramName,elementIndex) CREATE_INDEX(paramName,elementIndex)
#define STRINGIZE_1(x) STR1(x)
using namespace std;
int main()
{
int testArray;
for (unsigned int i = 0 ;i < 5 ; ++i )
{
// I want to create a MACRO such that it create "testArray[0]","testArray[1]",..."testArray[4]" etc.
CREATE_ARRAY_ELEM ("testArray",i);
}
return 1;
}