2

Trying to simplify writing boiler plate, but I get Field cannot have type 'void' and / or Expected ')'

Newbie c++, I've seen a bunch questions like this, but still can't figure it out. The errors are still too cryptic to me to able to google them..

#define GAME_STAT(Stat) \
    UPROPERTY(BlueprintReadOnly, Category = "Stats", ReplicatedUsing = OnRep_##Stat##) \
    FGameplayAttributeData ##Stat##; \
    GAME_STAT_ACCESS(UGameStats, ##Stat##); \
    UFUNCTION() \
    virtual void OnRep_##Stat##(const FGameplayAttributeData& Old##Stat##);
    
GAME_STAT("Health")

I want to generate the code with word "Health" instead of stand-in "Stat"

Thanks!

n-smits
  • 685
  • 7
  • 20
  • please include the error message in the question – 463035818_is_not_an_ai Oct 15 '20 at 14:49
  • 2
    `GAME_STAT(Health)`? – 273K Oct 15 '20 at 14:50
  • Check what `#` and `##` mean for the preprocessor, you'll find your solution. – YSC Oct 15 '20 at 14:51
  • Also, please show the c++ code that you want this macro to generate. – cigien Oct 15 '20 at 14:51
  • Thanks for the comments. I'll look it up. As for what code I want to generate, it's the same as already posted with instead of saying Stat actually saying Health. Will also update this to question. – n-smits Oct 15 '20 at 15:03
  • 1
    This won't work because the unreal header tool runs before the c++ pre processor. – George Oct 15 '20 at 16:51
  • @George thanks. Any way to actually do it? – n-smits Oct 15 '20 at 17:44
  • 1
    There's not really anything directly equivalent. I think what you might be wanting to do is create a stat component that owns an array of stat data, maybe a struct containing the stat name and associated FGameplayAttributeData. If you want to inject unique behaviour for your OnRep function then you could create a UStatBase class instead and give it a virtual OnRep function (instead of an array of structs you would then have an array of UStatBase*). – George Oct 15 '20 at 17:58
  • @George thanks I'll look into it. – n-smits Oct 15 '20 at 19:50

1 Answers1

3

## is for pasting tokens together, but it looks like you think it is "reverse stringification".
It's also a binary operator, not an "around-ary" operator.

That is,

#define hello(x) Hello_##x
hello(World)

will produce

Hello_World

This should work (but is thoroughly untested):

#define GAME_STAT(Stat) \
    UPROPERTY(BlueprintReadOnly, Category = "Stats", ReplicatedUsing = OnRep_##Stat) \
    FGameplayAttributeData Stat; \
    GAME_STAT_ACCESS(UGameStats, Stat); \
    UFUNCTION() \
    virtual void OnRep_##Stat(const FGameplayAttributeData& Old##Stat);
    
GAME_STAT(Health)
molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • Thanks. Lemme just play with this a bit and I'll be back to mark accepted. – n-smits Oct 15 '20 at 15:04
  • Thanks for the answer, unfortunately it doesn't seem to work for Unreal Engine - vars are declared correctly in source now, but not visible in engine >( but that's a different issue I guess so thanks for answering this! Cheers – n-smits Oct 15 '20 at 15:15