Linking error for constexpr auto

While rebuilding this project on my current system, I got some errors and corrected them. However I got a linking error I don’t understand. I have a solution but I have no idea if it’s a good one.

So there’s a .h/.cpp pair that draws the frequency grid. In the original (linking error) version there’s this variable definition in .h for the printing of frequency values:
static constexpr auto decadeStrings = { "10", "100", "1k", "10k" };

The variable is then used in the .cpp file (function: paintFrequencyGrid) a couple of times in this fashion:
drawFrequencyLabels(g, juce::StringArray(decadeStrings)[0], xPos, textBaseLine);

…and this produces a linking error:

Undefined symbols for architecture x86_64:
  "FrequencyDecibelGridOverlay::decadeStrings", referenced from:
      FrequencyDecibelGridOverlay::paintFrequencyGrid(juce::Graphics&) in libGEDDVASVF.a(FrequencyDecibelGridOverlay.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

…but I get a sucessfull build if I change the definition to:
const juce::StringArray decadeStrings = { "10", "100", "1k", "10k" };

So I’m guessing the auto keyword fails in this context but I’m not sure why. Anyone more fluent in C++ who can explain?

macOS 10.14.6
Xcode 11.3.1
C++ set to version 14 in Projucer

This is because some (but not all!) uses of constexpr objects require the object instances to be present in the generated binary. This often seems to happen when the address of a constexpr object is taken at runtime, although this doesn’t seem to be consistent between compilers and compiler versions.

It’s normally possible to work around the issue by providing a separate definition (as well as the declaration) of the constexpr object.

OK, thanks.
Is my “solution” a bad one in this case? Seems it’s a rather trivial use of the variable.

Otherwise when would this be bad? Using const someType instead of static constexpr auto

I think those options are basically fine, yeah. The main disadvantage is that you’ll get a separate copy of the StringArray for each instance of the FrequencyDecibelGridOverlay, but that’s only likely to be an issue if you create thousands of GridOverlay instances.

1 Like