@a light breeze Yep, that example is contrived, I made it to make a presentable example of my problem. Its just to highlight what will happen in production code if I have for example an “if constexpr(IsDefined)" which appears at different points in code when the first instance has been evaluated with an undefined type. As you correctly say, for the case where I static_assert it doesn't matter if the specialization gets set to “undefined” since that will mean that I have to include the type at that point before I can resume compilation (which is what I want).
Shaarigan said:
I guess the type you want to ref-count is known at the time when you put it into your function is it? If so, you can drive another route and instead test if the type has or doesn't has the needed functions right?
Yeah, thats the part that I already solved though. The problem occurs when a forward-declared type is passed to the SFINEA-evaluation-mechanism, which will make all further uses of the check will appear to report that the type doesn't have the required function (even though it actually has).
Shaarigan said:
SFINAE about type inheritance is very complicated and slow but there are also meta programming tricks you can use to determine presence of a certain function. So instead of looking for inheritance, you could look for that functions you need and if they exist, go the ref-count way and otherwise put a warning into console?
Fortunately I have access to concepts which makes this mindnumbindly easy. I'm glad I'm not stuck with an old version of c++ or have to maintain c-compatibility personally :P
irreversible said:
I'm not sure how all the refcounting really ties into this or what exactly you mean by bytecode (serialized data? interpreted code?), but I've given reflection enough thought to have figured out at least five difficulty levels and a quadrillion different ways of accomplishing it. And in C++ none of them are easy really.
I have a visual scripting-language which used to have a horrible “each node is a class”-model of execution. I'm in the process of writing a stack-based bytecode-compiler/interpreter for that. The type-system is the driving force behind the visual-scripting (every value-pin represents a value that is registered with the type-system). If an object-type is refcounted, every time it is returned from a node I need to assign it to a local variable and manage the lifetime of that, requiring additional instructions and in general complicating the code-gen. If a type is not ref-counted, I can just push the value on the stack and forget about it until it is consumed (in most cases).
irreversible said:
This sounds ambitious. I'm fairly fresh off of rewriting my serialization wrapper myself. I opted for inheriting from a common base, which gathers registered members and reads/writes them by offset and size. Having a common base allows me to process serialized objects hierarchically and super automatically with manual management necessary only for types that are too messy or require post-read initialization. I do need to manually register my types and serialized class members, though, but I also use them for storing/reading human-readable settings/properties where this kind of manual approach pays off (since I can group them in a meaningful way). I'm not really sure if your “type-system” is functionally related to serialization (it seems to be, among other things), but if I had to go about writing a “next level” reflection layer for an editor (e.g. one without a base class), I'd probably skip all other middleware solutions and go with an offline tool that parses the raw C++ source code at compile time and generates a metadata representation from that. As far as I know UE does its property management this way (I don't use it myself, so this is is from skimming the docs), presumably also Unity and a bunch of other frameworks. Not that I myself could write a parser for modern C++, that is…
Yeah, the type-system itself is fairly ambitious. But its at the core of my engine and is really what enabled me to be productive and write good tooling in the end.
I've worked with unreal, and while their pre-parser was pretty cool, it also resulted in a bunch of problems and made things really slow (in terms of compilation and IntelliSense). I also can't be bothered to deal with having to integrate some tooling into the IDE/compiler, and parse c++-files etc… though I would actually like to have it for the part where I have to register a types properties:
EventSystem::Declaration EventSystem::GenerateDeclaration(void) noexcept
{
return
{
L"Event",
{
{ L"EnableBackgroundCompilation", true, core::bindAttribute(&EventSystem::m_enableBackgroundCompilation, &EventSystem::OnBackgroundCompilationChanged) },
{ L"FullBackgroundCompilation", true, core::bindAttribute(&EventSystem::m_fullBackgroundCompilation) },
{ L"OpenMessagesOnBackgroundCompilation", true, core::bindAttribute(&EventSystem::m_openMessagesOnBackgroundCompilation, &EventSystem::OnOpenBackgroundCompilationChanged) }
}
};
}
That would be pretty neat to automate, but thats also not really part of the layer of the type-system that I was talking about in this post so far. This is more of a consumer of the type-system, where each call to “bindAttribute” will reference a member which is of a type known to the type-system (EventSystem itself has nothing to do with the type-system.
One last comment about the shared base-class/interface: That would also not be the be-all and end-all anyways, since “objects” is just one category in the type-system. I also have primitives (int/float/bool), enums and structs, which I definately don't want to put under one shared base-class (I'm not a fan of the “everything is an object”-paradigm and also the current system has a pretty minimal overhead for dealing with primitive types). I hope this is all somewhat understandable, I know that this is a complex system which one could write an entire online-documentation about (I did write a blog-post which unfortunately is horribly formatted know)
irreversible said:
I can identify with this. I it works, then it doesn't really matter how ugly it is on the inside ?. Right? RIGHT? (no, really - there's always a better architecture which you think of when you finish the current one)
Oh, I do refactor things a lot, perhaps way too much. This is by far not the first iteration of the type-system, and it will probably not be the last eigther :D