0

What I want to achieve:

A Blueprint Callable function that takes UPARAM(ref) bool& as a parameter which can but doesn't have to be passed inside of Blueprint Graph (variable doesn't have to be plugged into input pin to this node for the graph to compile). And by *asing on if the parameter has been passed or not, the function will behave in a slightly different way.

For example, I was able to create something like this in C++ (pastebin imgur):

void Func(bool& param = *(bool*)0)
{
    if (&param == nullptr)
        // do something
}

Above code compiles and consistently behaves in VS2022, allows to call Func() without passing any parameters in it and execute code basing on if the parameter has been passed which is the exact behavior that I'm looking for.

However, this code is a C++ undefined behaviour not allowed for UFUNCTIONs. So, when I try to declare something similar as BlueprintCallable UFUNCTION in Unreal, this of course will not compile:

UFUNCTION(BlueprintCallable)
static void Func(UPARAM(ref) bool& param = *(bool*)nullptr);

due to error:

C++ Default parameter not parsed: param "(bool)nullptr"

So my question is:

  • Is the "behaviour/functionality" that I want to achieve even possible in BlueprintCallable functions?
  • Is there any workaround to what I've described above? For example in form of macros, custom data containers or function specifiers?

I think summary of my question might be a little bit misleading. I just want to recreate this type of code/behaviour pastebin imgur in Unreal's 'UFUNCTION(BlueprintCallable)'. Yes, I understand that given example is an UB, but this is the closest result to what I want to create. This is just an example.

This question is Unreal Engine / UFUNCTION related. This is not a typical C++ issue. Unreal uses macros for UFUNCTION declaration and compiles in a different way than regular C++ (UFunctions). Because of that pointer cannot be used as parameter in this case as Unreal does not allow it. However pointer would be an actual solution to this question if it were only about pure C++.

Possible but not exact solutions:

  • meta = AutoCreateRefTerm( "param" ) can be specified in the UFUNCTION declaration. This allows Blueprint Node to have default value in pass-by-ref pin. However, with this approach another condition (bool pin) is needed because it is not possible check if actual variable gets passed or not.
  • In comments TOptional has been mentioned. This data container is actually something that exactly fits here, but TOptional cannot be used as parameter in BlueprintCallable UFUNCTION due to "Error: Unrecognized type 'TOptional' - type must be a UCLASS, USTRUCT, UENUM, or global delegate.", or at least I don't know how to use it.

My question has been closed as a dupe of Is null reference possible? which isn't true. My question asks for high level functionality in Unreal's Blueprints/UFUNCTIONS that would omit the need of "null reference". Something like TOptional::IsSet

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
i like bananas
  • 126
  • 1
  • 8
  • 2
    There's no such thing as a "null" reference. C++ does not work this way. The shown code is undefined behavior. – Sam Varshavchik Jul 23 '22 at 18:49
  • 2
    I'd suggest either writing a separate overload that doesn't take an argument or making it accept a `bool*` instead of a `bool&` if you want `nullptr` to be a valid option. – Nathan Pierson Jul 23 '22 at 18:59
  • 1
    I don't know blueprint, but if it's callback, I think there no reason to provide default argument? – apple apple Jul 23 '22 at 19:00
  • 2
    [Undefined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior) does not mean the code will definitely not compile, or definitely crash, or anything like that. It means that there are no restrictions on what behavior is permissible, according to the standard. In practice it means you can make very few assumptions about what will actually happen when you run your code. – Nathan Pierson Jul 23 '22 at 19:00
  • Hey, sorry for deletting last two comments. The weren't formated in the way I would like it to. I think summary of my question might be a little bit missleading but I have no idea how I was suppoused to correctly ask about it. I just want to recreate this code and behavior: https://pastebin.com/gfbXKVVw https://imgur.com/a/FCp5TSD In Unreal Engine. Because of that I cannot use pointers as parameters or function overloads. These are restricted for 'BlueprintCallable' functions. [EDITED] – i like bananas Jul 23 '22 at 19:11
  • @appleapple No this cannot be done by callback. This function needs reference as parameter to be able to change it. I kinda can achieve it via callback and additional conidion but it will be realy "messy". – i like bananas Jul 23 '22 at 19:21
  • 3
    Current C++ Draft Standard - [dcl.ref #5 note 2](https://eel.is/c++draft/dcl.ref#note-2) _"...In particular, __a null reference cannot exist__ in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior...."_ ie `*(bool*)nullptr` is indirection through a null pointer which causes UB. – Richard Critten Jul 23 '22 at 19:27
  • I guess `*(bool*)0` works exacly the same as `*(bool*)nullptr` in this case? Would `bool* param = (bool*)0` (pointer parameter) also be concerned as UB? I just trynna understand it because I've seen a lot of function declarations using it for pointer-type parameters. I fought that it can be also somehow used for references. Anyway thanks for all those comments! – i like bananas Jul 23 '22 at 19:52
  • 4
    `bool* param = (bool*)0` (or better `bool* param = nullptr`) is perfectly fine because it simply assigns a pointer value, it doesn't attempt to derefence a nullpointer. – UnholySheep Jul 23 '22 at 20:24
  • 1
    What about using Unreal's [`TOptional`](https://docs.unrealengine.com/5.0/en-US/API/Runtime/Core/Misc/TOptional/) instead? – Remy Lebeau Jul 23 '22 at 20:55
  • Hey @RemyLebeau, this is exacly a functionality that I was looking for! But I cannot declare the UFUNCTION with `TOptional` parameter since compiler throws `Error: Unrecognized type 'TOptional' - type must be a UCLASS, USTRUCT, UENUM, or global delegate.`. It works perfectly fine as regular local variable but not as parameter. Can you describe exacly how shall I aproach it? – i like bananas Jul 23 '22 at 21:17
  • 1
    *For example in standard C/C++ this can be done in this way `void Func(bool& param = *(bool*)0) { if (&param == nullptr) {...} }`* That is not standard C, and cannot be done that way in standard C. That is **undefined behavior** in C++, and cannot be done that way in standard C++. In the programming language **C/C++**, that is not legal syntax (since C/C++ language takes after OCaml). – Eljay Jul 23 '22 at 22:47
  • @Eljay Sure, I just edited out this line since there is already 5 comments about undefined behavior. The `Func(bool& param = *(bool*)0)` declaration is just an example of what I want to achieve in Unreal's BlueprintCallable UFUNCTION. I'm actually looking for workaround for it. Hope, after edits my question is more clear. – i like bananas Jul 23 '22 at 23:31
  • 1
    Code that has **undefined behavior** is not prevented from *compiling*. So merely because something compiles is insufficient to conclude that it does not contain any undefined behavior. – Eljay Jul 24 '22 at 02:34
  • @JaMiT As you said question was already tagged with 'UnrealEngine'. Though I just created EDIT2 paragraph that highlights it. I cannot specify every Unreal/UFUNCTION restriction since I'm not fully familiar with it. Hope this post gets more clear with every edit. – i like bananas Jul 24 '22 at 08:03
  • Hey @AnoopRana, this question relates more to Unreal's functionality than to C++ itself. I'm looking for workaround functionality to what I've described, not for pure "null reference". Can I get a reopen on this question? https://stackoverflow.com/questions/4364536/is-null-reference-possible does not answer it at all. – i like bananas Jul 24 '22 at 08:50
  • @ilikebananas you simply can not do it, it's illegal c++ (UB). If your question is "how can I have optional parameter in blueprint" you may ask a new question about it. – apple apple Jul 24 '22 at 08:58
  • strictly speaking you can bind it to alive object. BUT I believe there are better methods in blueprint anyway. (for example, overload the function or use pointer (just a guess)) – apple apple Jul 24 '22 at 09:01
  • for the UB part, it's not "it's OK in my current env" problem, you should never rely on it, for example, gcc optimize the compare out completely https://godbolt.org/z/81c7hhsj4 – apple apple Jul 24 '22 at 09:06

0 Answers0