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
#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
#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
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
#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
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;
}