Home > Software engineering >  define constants in a struct
define constants in a struct

Time:09-27

I'm trying to create a struct with some constants in it like this:

#include <CoreAudio/CoreAudio.h>
...
struct properties {
    //Volume control
    const AudioObjectPropertyAddress volume = {
        kAudioDevicePropertyVolumeScalar, //mSelector
        kAudioDevicePropertyScopeOutput, //mScope
        0 //mElement
    };
    //Mute control
    const AudioObjectPropertyAddress mute = { 
        kAudioDevicePropertyMute,
        kAudioDevicePropertyScopeOutput,
        0
    };
};

However, I cannot access the constants in this class;

//Function used to for example set volume level or set mute status
//bool setProperty(UInt32 data_to_write, AudioObjectPropertyAddress addr_to_write_to);
//Following line should mute the system audio
setProperty(1, properties::mute);

This will make the compiler return the following error:

error: invalid use of non-static data member 'mute'

So, I tried making the constants static like this:

const static AudioObjectPropertyAddress volume = { ...

But now, I get a different error:

error: in-class initializer for static data member of type 'const AudioObjectPropertyAddress' requires 'constexpr' specifier

The last thing I tried is changing const static to static constexpr, however again, I cannot access the constants. Every time I try to access them, the compiler show this error:

Undefined symbols for architecture x86_64:
  "properties::mute", referenced from:
      _main in main-fefb9f.o
ld: symbol(s) not found for architecture x86_64

I'm not really sure what's going on here, I tried converting my struct into a class, but I ended up getting the same Undefined symbols error. I know I could just define the two constants as global variables, but I thought putting them into a struct/class would make the code look "nicer" or just more organized. Could someone please explain what's wrong here and provide a possible solution?

CodePudding user response:

why not just properties.volume and properties.mute or use namespace otherwise...

namespace properties 
{
    //Volume control
    const AudioObjectPropertyAddress volume = {
        kAudioDevicePropertyVolumeScalar, //mSelector
        kAudioDevicePropertyScopeOutput, //mScope
        0 //mElement
    };

    //Mute control
    const AudioObjectPropertyAddress mute = { 
        kAudioDevicePropertyMute,
        kAudioDevicePropertyScopeOutput,
        0
    };
};

CodePudding user response:

  •   struct properties {
          //Volume control
          const AudioObjectPropertyAddress volume = {
              kAudioDevicePropertyVolumeScalar, //mSelector
              kAudioDevicePropertyScopeOutput, //mScope
              0 //mElement
          };
      };
    

    is valid, but volume is not a static member, so usage requires an instance:

    setProperty(1, properties{}.volume);
    
  • With static const, it would be:

    struct properties {
        //Volume control
        static const AudioObjectPropertyAddress volume;
    };
    
    const properties::AudioObjectPropertyAddress volume {
        kAudioDevicePropertyVolumeScalar, //mSelector
        kAudioDevicePropertyScopeOutput, //mScope
        0 //mElement
    };
    

    and usage might be the expected:

    setProperty(1, properties::volume);
    
  • with static constexpr in C 11/C 14:

    struct properties {
        //Volume control
        static constexpr AudioObjectPropertyAddress volume{
            kAudioDevicePropertyVolumeScalar, //mSelector
            kAudioDevicePropertyScopeOutput, //mScope
            0 //mElement
        };
    };
    
    const properties::AudioObjectPropertyAddress volume; // Definition when ODR-used
    
  • with static /*inline*/ constexpr since C 17:

    struct properties {
        //Volume control
        static /*inline*/ constexpr AudioObjectPropertyAddress volume{
            kAudioDevicePropertyVolumeScalar, //mSelector
            kAudioDevicePropertyScopeOutput, //mScope
            0 //mElement
        };
    };
    

CodePudding user response:

Here are a list of things you can try:

You could.... redesign your templating/types. Struct vs Namespace. Without seeing the whole project its tough to guide in a specific direction. Its up to you to decide if you need to use a struct, enum, namespace, class to encapsulate your code.

As for const static declaration. Here is a post describing valid methods of static class membder declarations. Pay close attention to your c version.

"Prior to C 11, only static const data members of integral or enumeration type could have initializers in the class definition."

Lastly, the static constexpr undefined. Is your static var in the same header/source file as where you are calling it? (Likely not, as the error shows the call from main). Static variables are not visible to other files.

If you want to modify static vars you could do so using a public get/set from a class function.

Suppose 'mute' is a single uint8_t value. Consider using a namespace with all static data declared as: static const uint8_t mute.

  • Related