C++: forward declare explicitly to make the code more robust

We currently forward declare classes as we use them in functions.
But this breaks if classes with the same name were declared in the
parent namespace. As shown with this example

```C++
// Uncomment that line to make the code break
//struct SharedGlobals;

namespace ns {
    // Is that a forward declaration in `ns`?
    // Depends if it was declared before in the parent namespace
    void foo(struct SharedGlobals *x) {}

    // Actualy define ns::SharedGlobal
    struct SharedGlobals { int x; };

    int xyz() {
        SharedGlobals globals;
        foo(&globals);
    }
}
```

So make sure we forward-declare the classes properly to be more robust
and be able to include generated file with namespace after a file
without namespace

CC #2909
This commit is contained in:
Olivier Goffart 2025-05-26 17:40:17 +02:00
parent 02203703e6
commit 2f2116686f
5 changed files with 60 additions and 5 deletions

View file

@ -4,4 +4,5 @@
add_executable(multiple-includes main.cpp logic.cpp)
target_link_libraries(multiple-includes PRIVATE Slint::Slint)
slint_target_sources(multiple-includes app-window.slint COMPILATION_UNITS 0)
slint_target_sources(multiple-includes another-window.slint NAMESPACE other COMPILATION_UNITS 0)

View file

@ -1,3 +1,5 @@
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> ; SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 -->
This is a test making sure that the header can be included in several file without causing multiple definitions
This is a test making sure that the header can be included in several compilation without causing multiple definitions
And also that we can include two different generated headers generated different namespaces in the same compilation unit

View file

@ -0,0 +1,29 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
import {Button, AboutSlint} from "std-widgets.slint";
export global Logic {
callback decrement(int) -> int;
}
export struct FooBar {
qrs: int, tuv: string
}
export component AnotherWindow inherits Window {
preferred-width: 800px;
preferred-height: 600px;
property <int> count: 100;
in property<FooBar> xxx;
VerticalLayout {
AboutSlint { }
Button {
text: "Hello";
clicked => { count = Logic.decrement(count); }
}
Text { text: count; }
}
}

View file

@ -3,10 +3,16 @@
#include "logic.h"
#include "app-window.h"
#include "another-window.h"
int main(int argc, char **argv)
{
auto my_ui = App::create();
setup_logic(my_ui->global<Logic>());
auto my_ui2 = other::AnotherWindow::create();
my_ui2->global<other::Logic>().on_decrement([](int x) { return x - 1; });
my_ui2->show();
my_ui->run();
}