How to use C++20 modules in an actor .cpp source code?

Hi there,

I’m trying to add some C++20 modules in the .cpp file. My project is based on Unreal Engine CPP Quick Start . After doing that, I got a floating rotating object. Now I want to import some modules, and below is my attempt:

Add a module file /Source/QuickStart/MyModule.ixx

export module MyModule;

export float MyFunc()
{
    return 20.0f;
}

Modify the build file /Source/QuickStart/QuickStart.Build.cs

using UnrealBuildTool;

public class QuickStart : ModuleRules
{
	public QuickStart(ReadOnlyTargetRules Target) : base(Target)
	{
		PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
	
		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });

		CppStandard = CppStandardVersion.Cpp20;
	}
}

Modify the cpp file /Source/QuickStart/FloatingActor.cpp

#include "FloatingActor.h"

import MyModule; // <--------- note

// Sets default values
AFloatingActor::AFloatingActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

    VisualMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
    VisualMesh->SetupAttachment(RootComponent);

    static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeVisualAsset(TEXT("/Game/StarterContent/Shapes/Shape_Cube.Shape_Cube"));

    if (CubeVisualAsset.Succeeded())
    {
        VisualMesh->SetStaticMesh(CubeVisualAsset.Object);
        VisualMesh->SetRelativeLocation(FVector(0.0f, 0.0f, 0.0f));
    }
}

// Called when the game starts or when spawned
void AFloatingActor::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AFloatingActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

    FVector NewLocation = GetActorLocation();
    FRotator NewRotation = GetActorRotation();
    float RunningTime = GetGameTimeSinceCreation();
    float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));
    NewLocation.Z += DeltaHeight    * MyFunc(); // <----- note
    float DeltaRotation = DeltaTime * MyFunc(); // <----- note
    NewRotation.Yaw += DeltaRotation;
    SetActorLocationAndRotation(NewLocation, NewRotation);
}

Then close the Unreal Editor, locate the project root path, right click “QuickStart.uproject”, click “Generate Visual Studio project files”, open “QuickStart.sln”, and rebuild project.

After that, I get this error:

1>E:\Unreal Projects\QuickStart\Source\QuickStart\FloatingActor.cpp(6): error C2230: could not find module 'MyModule'
1>E:\Unreal Projects\QuickStart\Source\QuickStart\FloatingActor.cpp(42): error C3861: 'MyFunc': identifier not found
1>E:\Unreal Projects\QuickStart\Source\QuickStart\FloatingActor.cpp(43): error C3861: 'MyFunc': identifier not found

I have checked the Solution Explorer and notice that MyModule.ixx is already contained in QuickStart/Source/QuickStart, so I don’t have a clue why the build system skipped it. Do you have same experiences and know how to fix it? Thanks in advance.

1 Like

I will try out the same tomorrow. Did you figure anything out in the meantime?

No. I use Visual Studio 2022 17.6.5 as my compiler, so I don’t think it’s because Visual Studio doesn’t support C++ module. I tried to specify its item type to C/C++ compiler manually (right click → properties) but it was ignored and still was skipped to compile.

I also tried on the newest Unreal 5.3.0 Preview, but I had no luck. They said they support C++20, but actually this important feature is missing.

This, plus the compiler you have installed should suffice to use C++ 20 features. I believe. I might be mistaken.

Trying out myself now

Visual Studio isn’t a compiler. But you’re right that your compiler isn’t your problem. Does Unreal 5.3.0 have any news regarding full C++20 support? I am not aware of that. Eventually C++20 will be the default - that’s all I hear.

I suspect the support for C++ modules requires changes to the Unreal Build Tool. And thus it won’t happen anytime soon.

In practice, Unreal C++ doesn’t support a lot of things. Given its reliance on Macros, it doesn’t support any C++ standard fully. E.g. you can’t have templated UCLASSes just to give you an example.

And if you try this

UCLASS()
export class MYAWESOMEGAME_API : public UObject
{
    GENERATED_BODY();
};

It fails, too. The export isn’t compatible with the UCLASS macro.

I tried to convert a header file into a C++20 module file and it just resulted in a non-sensical error, not even related to modules and only loosely related to the header file I touched.

EDIT: discourse reminded me that I am talking to myself. Not allwed. Therefore amending this post

Btw regarding the adaption of C++20 language features, I have very limited expectations.

Basically, as long as you don’t use any U-Macros, you are free to go crazy with all kinds of things, including but not limited to concepts, ranges, templated lambdas …

When you depend on any U-Macro, even basic stuff can break like templates. You can’t bind lambdas to dynamic delegates.

Certain things work, but differently.

E.g. you can’t have a uproperty that is a std::option, but there is TOptional.

You can’t use co-routines out of the box, but there is the UE5Coro plugin which even goes so far to integrate co-routines into the Gameplay Ability System.

To a certain degree, Unreal C++ is a fork of C++ with non-trivial rebasing. And any new C++ feature has to adapt to Unreal C++. In a better world, Unreal C++ would have developped alongside C++, implementing and improving with every C++ feature that comes newly available.

For bigger projects, it never plays out like that.

Just imagine an entity-component-system (Unreal Actors and Components) that make use of C++ concepts - how cool would that be. Instead, any new developments seem to focus primarily on Blueprint (well and visual design tools). The C+±base of Unreal is deemed ‘good enough’, and that is sadly true. So no progress there.

Sounds like it’s a too far future. Thank you for telling me these.

you should set bEnableCppModules=true; in project.target.cs

I recently tried to use it, but UBT had an error , could not properly handle the C++ module files (I forgot the specific error message). Is it working fine for you now? If so, I would like to continue using it.

From what I have been able to discern, C++20 modules are only supported on platforms that use MSVC to build. I don’t have insight into console builds, so this effectively means “Windows only” from what I can tell.

A few notes:

  • Module files must use the MSVC-format module extension (.ixx).
  • You muse set the bEnableCppModules flag to true in your project’s .target.cs file (thanks to @byTangs for the hint!).
  • The ClangToolChain class has (in UE 5.3, at least), zero knowledge about .ixx files, even though Clang itself supports a filename prefix that could be leveraged to make that work: -x c++-module. Presumably under the hood this would look like:
    clang++ -std=c++20 -x c++-module MyModule.ixx ...
    But, again, it doesn’t support this at all yet, so it doesn’t really matter.
    • This effectively means that C++20 modules that compile on Windows will not build on macOS or Linux (at least).

Hopefully Epic will complete adding support for C++20 modules to the engine soon, though that may require that platforms (e.g. macOS) start shipping newer versions of compilers in their standard toolchains (Apple’s current default is Clang 15 and Clang 16 appears to have solidified a few final pieces of the module puzzle for its implementation). :crossed_fingers:

3 Likes

To add a bit of reference here for the curious reader:

C++23 modularizes the entire standard library, so we can now write import std; to import everything with absolutely no drawbacks.

Microsoft has kind of taken their own road when it comes to naming conventions for module files, which is fine I guess, but it has not been standardized. GCC’s implementation of modules is severely limited, while Clang is probably okay from what I hear. We should wait until C++23 has settled before we can talk about how Unreal should best offer module support, because until then modules can only be an experimental feature.

Unreal 5.3 is built with C++20, so using features such as concepts is simple and easy.

I don’t think Epic can do much more until the standard is, well, standard. :slight_smile:

1 Like