I want to programmatically retrieve the identifier of a C++ class instance at runtime. I'm aware that C++ doesn't support reflection yet, but is there any alternative solution out there?
For instance, given the following example:
class Foo {
Foo() {
auto name = reflect::getIdentifierName(this);
std::cout << name << std::endl;
}
};
void main() {
Foo my_obj;
}
Executing this program should print out "my_obj".
I'm looking for any utility library that I could use to implement this basic reflection function.
I'm particularly wondering if libclang can be used to extract such information - if so, any hint for how to build the reflect function to do this.
Yes, but this is implementation defined. Proceed at your own risk.
Yunnosch's suggestion sounds much more reasonable without more context.
#include <iostream>
#include <typeinfo>
class Foo {
public:
Foo() {
const char * const name = typeid(this).name();
std::cout << name << std::endl;
}
};
int main()
{
Foo my_obj;
}
Related
Can I send an instance to a function not by using the . operator?
For example:
// header file
class A
{
public:
void foo() {std::cout << "Hello" << std::endl;}
};
// main file
A instance = new A;
instance.foo();
// instead do something like this
A::foo(instance);
Can I do something like that?
Yes, you can indirectly via std::invoke:
#include <functional>
#include <iostream>
struct A {
void foo() {
std::cerr << "hi\n";
}
};
int main() {
A a;
std::invoke(&A::foo,a);
}
But std::invoke's implementation will internally probably just apply the .* operator.
You're more than welcome to use the pointer to member syntax.
A instance;
auto fn = &A::foo;
(instance.*fn)();
.* is a different operator than .. Whether this is more readable is left as an exercise to the reader (hint: it's not)
I am trying to use the boost::signals2 functionalities in my program.
In my "Main Class" called "Solid" I have a member which I initialize inside the constructor body (so after the member initializer list) like this:
pointer_M = boost::make_shared<OtherClass>(/*parameters,...*/);
If the signal is triggered by some function I do not want to call a member of "OtherClass" (to which pointer_M points) but a member from "Solid", i.e. the class which initialized pointer_M just.
I tried the following:
boost::signals2::connection tria_signal = /*...*/.connect( boost::signals2::signal<void()>::slot_type(&Solid::call_this_function, pointer_M.get()).track(pointer_M) );
"call_this_function" is a member function of Solid. Unfortunately there are a bunch of error messages. "OtherClass" and "Solid" are not related by inheritance.
I would appreciated getting some advice how to fix my issue since I am very unexperienced with boost.
Best
But is that what I am trying to achieve possible at all?
The point is we can't tell without a clearer description. It sure sounds like a no-brainer: signals are specifically used to decouple callers and callees.
So let me just make up your "dummycode" for you. I'm going to sidestep the enormous type-overcomplication that you showed in that line:
boost::signals2::connection tria_signal =
/*...*/.connect(boost::signals2::signal<void()>::slot_type(
&Solid::call_this_function, pointer_M.get())
.track(pointer_M));
The whole idea of slots is that they generalize callables using type erasure. Just provide your callable in any compatible form and let the library deduce the arcane implementation types.
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
auto tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.pointer_M->test();
}
Prints
Solid was here
Crystal Ball: Can We Guess The Problem?
Maybe we can guess the problem: it looked like you were putting effort into tracking the lifetime of the object pointed to by pointer_M. That's not useful, since that OtherClass owns the signal in the first place, meaning that all connections are disconnected anyways when the OtherClass disappears.
Correct Lifetime Management
What you likely want is for the connection to disconnect when the lifetime of the Solid object ends, not the OtherClass. In general, I'd suggest using scoped_connection here:
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
boost::shared_ptr<OtherClass> pointer_M;
Solid() {
pointer_M = boost::make_shared<OtherClass>(1,2,3);
tria_signal = pointer_M->tria.connect(
boost::bind(&Solid::call_this_function, this));
}
private:
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
boost::shared_ptr<OtherClass> keep;
{
Solid s;
std::cout << "Testing once:" << std::endl;
s.pointer_M->test();
keep = s.pointer_M; // keep the OtherClass alive
} // destructs Solid s
std::cout << "Testing again:" << std::endl;
keep->test(); // no longer connected, due to scoped_connection
}
Prints
Testing once:
Solid was here
Testing again:
Simplify
In your case, the OtherClass is already owned by the Solid (at least it is created). It seems likely that having the shared-pointer is not necessary here at all:
Live On Coliru
#include <boost/signals2.hpp>
#include <boost/make_shared.hpp>
#include <iostream>
struct OtherClass {
OtherClass(...) {}
boost::signals2::signal<void()> tria;
void test() {
if (!tria.empty())
tria();
}
};
struct Solid {
Solid() : oc_M(1,2,3) {
tria_signal = oc_M.tria.connect(
boost::bind(&Solid::call_this_function, this));
}
void test() { oc_M.test(); }
private:
OtherClass oc_M;
boost::signals2::scoped_connection tria_signal;
void call_this_function() {
std::cout << "Solid was here" << std::endl;
};
};
int main() {
Solid s;
s.test();
}
Because the members are destructed in reverse order of declaration, this is completely safe.
Architecture Astronauting
If you know what you're doing, and the pointer_M actually needs to be shared, then likely you want to track that pointer. You should probably be considering making Solid also enable_shared_from_this. If you want to be really "Enterprise Grade Engineer™" about it, you could perhaps do something fancy with the aliasing constructor: What is shared_ptr's aliasing constructor for?
why does this code work? with c++14
// Example program
#include <iostream>
#include <string>
using namespace std;
auto fun()
{
struct a
{
int num = 10;
a()
{
cout << "a made\n";
}
~a()
{
cout << "a destroyed\n";
}
};
static a a_obj;
return a_obj;
}
int main()
{
auto x = fun();
cout << x.num << endl;
}
how is the type a visible in main? if i change auto x= to a x= it obviously doesn't compile, but how does main know about the type a?
The static declaration is there since I was trying to test for something else but then I stumbled upon this behavior.
Running it here: https://wandbox.org/permlink/rEZipLVpcZt7zm4j
This is all surprising until you realize this: name visibility doesn't hide the type. It just hides the name of the type. Once you understand this it all makes sense.
I can show you this without auto, with just plain old templates:
auto fun()
{
struct Hidden { int a; };
return Hidden{24};
}
template <class T> auto fun2(T param)
{
cout << param.a << endl; // OK
}
auto test()
{
fun2(fun()); // OK
}
If you look closely you will see this is the same situation as yours:
you have a struct Hidden which is local to fun. Then you use an object of type Hidden inside test: you call fun which returns a Hidden obj and then you pass this object to the fun2 which in turn has no problem at all to use the object Hidden in all it's glory.
as #Barry suggested the same thing happens when you return an instance of a private type from a class. So we have this behavior since C++03. You can try it yourself.
C++14 is made to be more and more tolerant with auto. Your question is not clear, because you're not stating what the problem is.
Now let's tackle your question differently: Why does it not work with a x = ...?
The reason is that the struct definition is not in the scope of the main. Now this would work:
// Example program
#include <iostream>
#include <string>
using namespace std;
struct a
{
int num = 10;
};
auto fun()
{
static a a_obj;
return a_obj;
}
int main()
{
a x = fun();
cout << x.num << endl;
}
Now here it doesn't matter whether you use a or auto, because a is visible for main(). Now auto is a different story. The compiler asks: Do I have enough information to deduce (unambiguously) what the type of x is? And the answer is yes, becasue there's no alternative to a.
I want to create a static function pointer array, so I can jump to a certain function regarding a received index. Like an index jumper.
So imagine a class like this:
Class A
{
private:
static void 1stFunction();
static void 2ndFunction();
static void(*functionPointer[20])(void);
};
Then I would like that functionPointer to get the value of the 1stFunction and 2ndFunction, and maybe even more.
So, how do I initialize it?
As far as I know, when a static member is declared, you can use it even before an instance is created. So I though, lets initialize that function pointer, so later I can call it like this
functionPointer[receivedIndex]();
So i tried to initilize it like this, in the same .h file
void (*A::functionPointer[])(void) =
{
A::1stFunction,
A::2ndFunction,
};
But the compiler gives me redifinition, it says it's already created.
So, pretty sure I'm missing something. I don't know though, if it is syntax or simply it is not possible to do it this way.
I know that function pointers to class's member functions are different than normal function pointers... But this is a static function, so I believe it doesn't belong to an instance and therefore it should work with normal function pointers.
Any help would be appreciated.
Thanks
The following would be a working example that probably achieves what you need.
You need C++11 for the initializer list.
It is a good practice to initialize the static member in the cpp file, as you don't want to have a definition of the static member everytime the header is included (this can lead to linking issues).
You can call callf with the desired index and have the corresponding function called, based on the initialization of the function pointer array.
The output of the program would be:
I am 2ndFunction
Header file
class A
{
private:
static void Function1();
static void Function2();
static void(*functionPointer[20])();
public:
static void callf(int index);
};
Implementation
#include <iostream>
#include "ex.h"
void(*A::functionPointer[20])() {
A::Function1,
A::Function2
};
void A::Function1() {
std::cout << "I am 1stFunction" << std::endl;
}
void A::Function2() {
std::cout << "I am 2ndFunction" << std::endl;
}
void A::callf(int index) {
A::functionPointer[index]();
}
int main(int argc, char const *argv[]) {
A::callf(1);
return 0;
}
Here you have a more modern C++ approach (C++14 needed)
I would advise you to explore lambda functions if you are not restricted to C++03.
#include <iostream>
#include <functional>
#include <vector>
class A {
public:
using f_type = std::function<void(void)>;
f_type f1 = []() { std::cout << "f0" << std::endl;};
f_type f2 = []() { std::cout << "f1" << std::endl;};
static void f3() { std::cout << "f3" << std::endl; }
std::vector<f_type> functions{f1, f2, f3};
};
int main() {
A a;
a.functions[0]();
a.functions[1]();
//adding custom lambda
a.functions.emplace_back([](){ std::cout << "custom f" << std::endl;});
a.functions[2]();
return 0;
}
you can add both functions and lambdas to your container.
I need to print the type of a parameter in a C++ source file using the clang API.
If I have a parameter representation in clang (ParmVarDecl* param) I can print the name of the parameter using param->getNameAsString(). I would need a method param->getTypeAsString(), but there is no such method. So is there another way to do this task?
Got the answer to my question in the llvm irc:
There is a method std::string clang::QualType::getAsString(SplitQualType split)
So this does work for me:
ParmVarDecl* param = *someParameter;
cout << QualType::getAsString(param->getType().split()) << endl;
You can use typeid to get the name of any type. Although it will vary from compiler to compiler, and may not be a pretty name.
#include <iostream>
#include <typeinfo>
struct MyStruct { };
int main()
{
std::cout << typeid(MyStruct).name() << std::endl;
}
If you need to do this for a lot of classes, you could make the call part of a base class, then any class that needs the functionality can just inherit from it.
#include <iostream>
#include <typeinfo>
class NamedClass
{
public:
virtual ~NamedClass() { }
std::string getNameAsString()
{
return typeid(*this).name();
}
};
class MyStruct : public NamedClass
{
};
int main()
{
MyStruct ms;
std::cout << ms.getNameAsString() << std::endl;
}