Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Schmerm
Sep 1, 2000
College Slice
Basic question. Why does this work:

code:
char array[] = {'a', 'b', 'c'};
but not this:

code:
const char* array = {'a', 'b', 'c'};
and why aren't they equivalent, when the following two things ARE equivalent and both compile to the same thing:

code:
char array[] = {'a', 'b', 'c', 0};
const char* array = "abc";
The question being: why does a ""-based literal resolve to a const pointer to a pre-allocated bit of static memory, while the {}-based constant doesn't?

Schmerm fucked around with this message at 19:51 on Oct 28, 2014

Adbot
ADBOT LOVES YOU

Schmerm
Sep 1, 2000
College Slice
Okay, I have a C++ RTTI conundrum. I need to test whether class A is a subclass of class B without having instances of either class lying around (so I can't just dynamic_cast).

Schmerm
Sep 1, 2000
College Slice

Jabor posted:

This seems unrelated to RTTI, since you can get what you need using entirely static information. You could probably just use is_convertible to check whether an instance of A would be implicitly convertible to an instance of B, without actually needing to have an instance on hand.

Cool! All these type query utility thingies are pretty useful. Unfortunately, I can't use is_convertible in my case :( I'm creating a facility to register a C++ class and bind it with some scripting language stuff. Each time I register a class, I want to scan through all the already-registered classes and see if the incoming class is a subclass of any of them, and use that information to update the ordering/relationship of the registered classes. There's dynamic behaviour in there.

Schmerm
Sep 1, 2000
College Slice
I create Lua bindings for C++ classes. Each class must be explicitly registered with a function call that looks something like:

code:
register_class<CPPClass>("ClassNameInLua", table_of_instance_methods, table_of_static_methods);
...where the instance/static methods are lists of <string, functionpointer> pairs. These register_class calls are wrapped in a nice way that is similar to how LLVM compiler passes register themselves.

When register_class() is called, it adds a new entry to a list of registered classes. Each entry is a structure that looks like this:

code:
struct RTTIEntry
{
    const char* lua_name;
    list_of_stuff instance_method_table;
    list_of_stuff static_method_table;
    std::function<bool(Object*)> check_instance;
};
The first three entries are just the function arguments to register_class(). The last entry is interesting. Background: all the C++ classes available to Lua derive from a class called Object. Not that it's important, but it's similar to the Unity Engine's entity/component model (where you can attach/detach arbitrary Aspects onto an Object at runtime), but I also still have a hierarchy of concrete classes deriving from Object (unlike Unity where everything is an Object, period, I think).

check_instance is a function, which given an Object at runtime, will tell you whether or not that Object is of a class derived from the registered class. The actual lambda assigned to check_instance is:

code:
entry.check_instance = [](Object* o)
{
    return dynamic_cast<CPPClassBeingRegistered*>(o) != nullptr;
});
This list of registered classes, and this curious check_instance function, are used whenever Lua calls C++, and the C++ code wishes to return a handle to a C++ object back to Lua. The returned handle must have the right lua_class_name associated it, so that the Lua code knows which table of instance methods can be called on it. Here's the sequence of events that happens when C++ code wishes to return an instance of a subclass of Object to Lua:

1) The C++ function has an instance of something, but hidden behind a base-class Object* pointer.
2) The list of RTTIEntries is scanned, and each entry's check_instance() is called on the Object* pointer.
3) The first entry that returns true is selected as the Lua class that correspods to the Object*'s actual run-time type.
4) Hooray, that entry's lua_name can now be used to tell Lua what class the returned handle is going to be.

---

What's missing from this system is a way to order the list of RTTIEntries such that if there exist several registered C++ classes that are related to each other, the most-derived classes come first, since they will be encountered first on the linear search in step 3). This is why, during register_class, I'd love to be able to examine the RTTIEntry list and find a smart place to insert the new entry, based on class relationships, without having any instance of anything lying around.

Schmerm
Sep 1, 2000
College Slice

The Laplace Demon posted:


You can get around constructing an object by (ab)using exceptions.


:monocle: sweet mother of satan! :monocle:

Yep, I think that'll do.

edit: I also didn't know that a standard C-like function pointer can point to a lambda, and thought only std::function could do that
edit2: this will gently caress with the debugger when it's set to break-on-throw, but filtering should fix that

Schmerm fucked around with this message at 19:28 on Jan 20, 2015

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply