C++ Simple Reflection without Macros: Print Variable Name and Its Value - c++

Is there a non-macro way in C++ of printing a variable name with its value. Here is the macro way:
#define SHOW(a) std::cout << #a << ": " << (a) << std::endl
PS: I'm using Linux and do not need a cross-platform solution

No, C++ does not support reflection and the only way of doing this (as far as I know) are with macros.

You can use dynamic symbols, but then it will only work in shared libraries or executables compiled with the -rdynamic flag. And it will recognize just global variables with default dynamic visibility.
#include <dlfcn.h>
#include <iostream>
int NameMe = 42;
const char *GetName(const void *ptr)
{
Dl_info info;
if (dladdr(ptr, &info))
return info.dli_sname;
else
return NULL;
}
template<typename T>
void Dump(const T &t)
{
const char *name = GetName(&t);
if (name)
std::cout << name;
else
std::cout << "<unknown>";
std::cout << ": " << t << std::endl;
}
int main()
{
int NoName = 33;
Dump(NameMe);
Dump(NoName);
return 0;
}
$ g++ dump.cpp -ldl -rdynamic
$ ./a.out
NameMe: 42
<unknown>: 33

No way.
Without macro, you've to do this:
std::cout <<"a : " << a << std::endl;
No other way.

If you can have all your classes derive from a common ancestor, you can provide a virtual function that accomplishes this. I haven't tried this template, it might not work - some feedback would be appreciated.
struct Reflector
{
virtual void Show() = 0;
};
template<class a, char name[]>
struct ReflectorImpl : public Reflector
{
virtual void Show()
{
std::cout << name << ": " << *this << std::endl;
}
};
class MyClass: public ReflectorImpl<MyClass, "MyClass">
{
};

Yes; in C++17 you can use PFR (in C++17 mode) to get nontrivial levels of non-macro reflection. There are related mechanisms for reflecting the "string-value" of an enum.
See https://github.com/apolukhin/magic_get ;
And https://github.com/Neargye/magic_enum .

Related

Variable enum 'class' in c++

I use something like in the following code fairly often:
// myclass.h
class MyClass {
public:
enum MyEnum { E1, E2, NUMMYENUM };
const char* kMyEnum[NUMMYENUM] = {"e1", "e2"};
const char* MyEnum2Char(MyEnum me) { return kMyEnum[me]; }
enum MySEnum { SE1, SE2, NUMMYSENUM };
static const char* kMySEnum[NUMMYSENUM];
static const char* MySEnum2Char(MySEnum se) { return kMySEnum[se]; }
void foo(MyEnum me) {
//do something, e.g. print
std::cout << MyEnum2Char(me) << "maps to " << emap[me] << "\n";
}
void bar(MySEnum se) {
//do something, e.g. print
std::cout << MySEnum2Char(se) << "maps to " << semap[se] << "\n";
}
private:
std::map<MyEnum, int> emap;
std::map<MySEnum, int> semap;
};
// myclass.cc
#include "myclass.h"
const char* MyClass::kMySEnum[MyClass::MySEnum::NUMMYSENUM] = {"se1", "se2"};
The way of generating an enum, a char* array and a function converting enum to char seems to add avoidable clutter and I am wondering if there isn't another way to achieve this? Something like the following isn't possible for multiple reasons, but might give you an idea of what I'd like to have:
// myclass.h
class MyClass {
public:
MyVariableEnumClass MyEnum(E1, "e1", E2, "e2");
static MyVariableEnumClass MySEnum;
void foo(MyEnum me) {
//do something, e.g. print
std::cout << me.string() << "maps to " << emap[me] << "\n";
}
void bar(MySEnum se) {
//do something, e.g. print
std::cout << se.string() << "maps to " << semap[se] << "\n";
}
private:
std::map<MyEnum, int> emap;
std::map<MySEnum, int> semap;
};
// myclass.cc
#include "myclass.h"
MyVariableEnumClass MyClass::MySEnum = MyVariableEnumClass(SE1, "se1", SE2, "se2");
Is there a way to achieve something 'clutter-free' like this? Maybe using macros?
A technique called XMacro can be used in C++ 11 as well as older versions of C++ and C to easily define consistent look-up tables for translating enums to strings.
First, you write an external file (let's call it my_class.xmacro) which includes the following:
#define SE_ENUM_TABLE \
ENTRY(SE1) \
ENTRY(SE2)
Next in your H file you include my_class.xmacro define the following:
#include "my_class.xmacro"
enum SeEnum{
#define ENTRY(a) a,
SE_ENUM_TABLE
#undef ENTRY
};
const std::string seEnumString[] = {
#define str_macro(a) #a
#define ENTRY(a) str_macro(a),
SE_ENUM_TABLE
#undef ENTRY
};
The macros inside seEnumStringId take ENTRY(a) and transform it to "a". So after pre-processor is finished with this file, it actually looks to the compiler as follows:
enum SeEnum{
SE1,
SE2
};
const std::string seEnumString[] = {
"SE1",
"SE2"
};
Using this technique you ensure that adding an enum will automatically create string id in the RIGHT order, and this technique can be used to generate additional types of look-up tables as well.

Where to put function declaration?

Let's say I'm developing a logging functionality. Inside logging.h I declare the function to be used by the application later on.
// logging.h
#include <string>
namespace logging {
void LogThis(const std::string& text);
}; // namespace logging
Its definition is obviously inside logging.cpp:
// logging.cpp
void logging::LogThis(const std::string& text) {
std::cout << "Log: " << text << '\n';
}
Now lets pretent that my LogThis function's work is split up into some smaller helper functions. They're not part of the logging interface. Let's take a Prettify function as an example.
// logging.cpp
void logging::LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << '\n';
}
My question is: Where do I put the function declaration of Prettify? I shouldn't include it in the logging.h header file, because then it can be called by other compilation units and its not part of the interface. So just put it inside logging.cpp instead like this?
// logging.cpp
namespace logging {
void Prettify(std::string& ugly_text);
void LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << '\n';
}
void Prettify(std::string& ugly_text) {
// making it pretty...
}
}
I'm looking for some best practices / rules of thumb / opinions on this :) Thanks in advance!
For things that are only needed within the file, I would just place it in an anonymous namespace within the C++ file itself, sort of the modern equivalent of the legacy C static keyword on functions(a):
namespace {
void WeaveMagic(std::string& ugly_text) {
WeaveMoreMagic(ugly_text);
}
void Prettify(std::string& ugly_text) {
WeaveMagic(ugly_text);
}
}
If you place this before any use of the functions, and ensure a strict hierarchy of calls, you can skip the declarations since the definitions provides the required information, as shown above.
Of course, if there are any circular dependencies between multiple anonymous functions (i.e., circular recursion), you will still need to provide declarations:
#include <iostream>
namespace {
int DivThree(int val); // needed to implement AddOne()
int AddOne(int val) {
std::cout << "AddOne " << val << " -> " << (val + 1) << '\n';
if (val > 0) return DivThree(val + 1);
return val;
}
int DivThree(int val) {
std::cout << "DivThree " << val << " -> " << (val / 3) << '\n';
return AddOne(val / 3);
}
}
int main(){
int final = AddOne(18);
std::cout << "Final " << final << '\n';
return 0;
}
And, yes, that's very contrived, but good examples of circular recursion are few and far between :-) The output is:
AddOne 18 -> 19
DivThree 19 -> 6
AddOne 6 -> 7
DivThree 7 -> 2
AddOne 2 -> 3
DivThree 3 -> 1
AddOne 1 -> 2
DivThree 2 -> 0
AddOne 0 -> 1
Final 0
(a) CPP Core Guidline SF.22 actually covers this:
Use an unnamed (anonymous) namespace for all internal/non-exported entities.
Reason: Nothing external can depend on an entity in a nested unnamed namespace. Consider putting every definition in an implementation source file in an unnamed namespace unless that is defining an "external/exported" entity.
An API class and its members can't live in an unnamed namespace; but any "helper" class or function that is defined in an implementation source file should be at an unnamed namespace scope.
If you are operating on functions only, as #paxdiablo have written, you can use anonymous namespace (look at his answer).
I have some C-based habits, so personally I would also see it as static function. But I'm not sure how C++ fanatics will look at it :). static (in this context) makes functions local for compilation unit (logging.cpp), so it cannot be linked from outside.
//logging.cpp
static void Prettify(std::string& ugly);
void LogThis(const std::string& text) {
Prettify(text);
std::cout << "Log: " << text << '\n';
}
static void Prettify(std::string& ugly) { }
However if your logging utility would be object-oriented. I suggest you to use D-pointer and Q-Pointer design pattern (known also as PImpl idiom) - https://en.cppreference.com/w/cpp/language/pimpl .
//logging.h
#include <string>
class loggingImpl;
class logging {
public :
logging();
virtual ~logging();
void LogThis(const std::string& text);
protected :
loggingImpl *impl;
};
//logging.cpp
class loggingImpl
{
public :
loggingImpl(logging *p) : qptr(p) { }
void Prettify(std::string& ugly) { }
//anything what you need and should be hided
// access parent through qptr
protected :
logging *qptr;
};
logging::logging() : impl(new loggingImpl) { }
logging::~logging() { delete impl; }
void logging::LogThis(const std::string& text) {
impl->Prettify(text);
std::cout << "Log: " << text << '\n';
}
As you have written, putting declaration in header file is not proper due to limiting visibility of unused symbols.

C++ function specialization behaves different for plain types and classes

i have this piece of code (http://coliru.stacked-crooked.com/a/ee05a00fc8ab5057):
#include <type_traits>
struct unregistered;
unregistered register_type(...);
template<class T>
constexpr bool is_registered = !std::is_same_v<unregistered, decltype(register_type(std::declval<T>()))>;
template<class T>
struct test_registration
{
static_assert(is_registered<T>, "Type is not registered!");
};
struct foo{};
struct bar{};
void register_type(int);
void register_type(char);
void register_type(void*);
void register_type(foo);
void register_type(foo*);
#include <boost/core/demangle.hpp>
#include <iostream>
int main()
{
std::cout << boost::core::demangle(typeid(test_registration<foo>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<foo*>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<int>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<char>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<void*>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<long>).name()) << "\n";
std::cout << boost::core::demangle(typeid(test_registration<bar>).name()) << "\n";
return 0;
}
The compiler generates errors for the calls using int, char, void*, long and bar.
I expect the errors for long and bar.
What I do not understand is:
Why are int, char, and foo treated differently?
Why are void*, and foo* treated differently? (both are ptrs)
I assume the reason has to do with foo beeing class type and int and char beeing plain types.
I would like to know the reason. Is it a compiler bug or is there some passage in the standard explaining this behaviour?
What I am asking is not how I can fix this problem (see link to coliru for a fix).
What I want to know is why it is behaving like this.

Is there a way to get a signature based typeinfo mangled function name using RTTI?

I want to use RTTI and mangled function (pointer) type strings.
Before you categorize this as an XY problem, I'm aware that there are better options to bind functions using polymorphism etc.
This is a purely academical question how to use typeid() properly with function pointers that should differ by their legally overloaded signatures.
If I use the following code, it seems I can retrieve unique typeinfo::name() values for various namespaces/types:
#include <iostream>
#include <typeinfo>
#include <string>
void foo(int) {
}
namespace woozle {
void goozle(int) {}
}
struct bar {
void baz(int) {}
static void boo(int) {}
};
int main() {
std::cout << typeid(&foo).name() << std::endl;
std::cout << typeid(&woozle::goozle).name() << std::endl;
std::cout << typeid(&bar::baz).name() << std::endl;
std::cout << typeid(&bar::boo).name() << std::endl;
}
The output is:
PFviE
PFviE
M3barFviE
PFviE
Perfectly what I expected (I assume the i in the mangled name refers to the parameter signature).
Now I want to have something like this (which is perfectly legal function overloading):
#include <iostream>
#include <typeinfo>
#include <string>
void foo(int) {
}
void foo(std::string) {
}
namespace woozle {
void goozle(int) {}
void goozle(std::string) {}
}
struct bar {
void baz(int) {}
static void boo(int) {}
void baz(std::string) {}
static void boo(std::string) {}
};
int main() {
std::cout << typeid(&foo).name() << std::endl;
std::cout << typeid(&woozle::goozle).name() << std::endl;
std::cout << typeid(&bar::baz).name() << std::endl;
std::cout << typeid(&bar::boo).name() << std::endl;
}
and of course the compiler complains about ambiguity:
main.cpp: In function 'int main()':
main.cpp:24:25: error: address of overloaded function with no contextual type information
std::cout << typeid(&foo).name() << std::endl;
^~~~
main.cpp:25:25: error: address of overloaded function with no contextual type information
std::cout << typeid(&woozle::goozle).name() << std::endl;
^~~~~~~
main.cpp:26:25: error: address of overloaded function with no contextual type information
std::cout << typeid(&bar::baz).name() << std::endl;
^~~~
main.cpp:27:25: error: address of overloaded function with no contextual type information
std::cout << typeid(&bar::boo).name() << std::endl;
^~~~
TL;DR
What is the proper syntax to specify a specific function overload with typeid() (if there is any)?
How can I provide the "contextual type information" that is demanded from the error message?
I'm coming from here in deep thinking mode.
To select a specific function from a set of overloaded functions you can use use the cast notation:
std::cout << typeid(static_cast<void (*)(int)>(foo)).name() << std::endl;
std::cout << typeid(static_cast<void (*)(std::string)>(foo)).name() << std::endl;
std::cout << typeid(static_cast<void (bar::*)(int)>(&bar::baz)).name() << std::endl;
std::cout << typeid(static_cast<void (bar::*)(std::string)>(&bar::baz)).name() << std::endl;
Specifically with typeid though, if you have the type already written down, you can skip the actual function name.
std::cout << typeid(void (*)(int)).name() << std::endl;
is shorter and does the job just as well.

Capture this in lambda attribute inside a templated class vs not-templated class

I have succeeded writing a class like this one, capturing this in a lambda defined as non-static attribute of said class:
#include <memory>
#include <iostream>
#include <functional>
struct S
{
S()
{
std::cout << "S::S()[" << this << "]" << std::endl;
}
std::string y_{"hi mate"};
int x_;
std::function<void(int*)> del_{[this](int *ptr)
{
std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
}};
std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};
int main()
{
S s;
}
This compiles and seems to run just fine.
However, with a templated class, it doesn't work anymore:
#include <memory>
#include <iostream>
#include <functional>
template <typename>
struct S
{
S()
{
std::cout << "S::S()[" << this << "]" << std::endl;
}
std::string y_{"hi mate"};
int x_;
std::function<void(int*)> del_{[this](int *ptr)
{
std::cout << "Deleting ptr[" << ptr << "] this[" << this << "] this->y_[" << this->y_ << "]" << std::endl;
}};
std::unique_ptr<decltype(x_), decltype(del_)> unique_{&x_, del_};
};
int main()
{
S<int> s;
}
$> g++ -std=c++1y custom_deleter_template.cpp
~/test custom_deleter_template.cpp: In instantiation of ‘struct
S::’: custom_deleter_template.cpp:9:3: required
from ‘S< >::S() [with
= int]’ custom_deleter_template.cpp:24:10:
required from here custom_deleter_template.cpp:15:35: internal
compiler error: in tsubst_copy, at cp/pt.c:12569
std::function del_{[this](int *ptr)
^ Please submit a full bug report, with preprocessed source if appropriate. See
for instructions.
Preprocessed source stored into /tmp/pyro/ccxfNspM.out file, please
attach this to your bugreport.
Before filing a bugreport (which I can't do, they blocked account creation), is it normal that it does not compile, based on what the standard says?
Compiler is g++ (Ubuntu 4.9.2-0ubuntu1~14.04) 4.9.2, used flag -std=c++1y. Same thing happens with flag -std=c++11.
This is indeed a bug in GCC, which is already being tracked.
It seems to affect 4.8 and 4.9. As pointed out in the comments this particular example works fine for 4.7 and 5.0. You can see that for yourself here and play with the different versions of gcc.
However this reduced version of your code with no external dependency still crashes with 5.0:
template <typename>
struct S {
int f{[this](){return 42;}()};
};
int main(){
return S<int>{}.f; // should return 42
}
I would suggest that you wait for the bug I referenced to be fixed before using your code, or switch to another compiler ;).