4

in our code, we need to handle configurations and in order to do that we need to pass the configuration names as std::string to our own framework.

Sample code:

framework.handle_config("enable-radio-link")
framework.handle_config("enable-tv-link")
framework.handle_config("enable-gateway-link")
so on to ...n

These strings will be written only in one place and they won't be repeated anywhere else.. except for only 2 or 3 configurations.

My team mate wanted to have it as #define and use, as it as best practice. like

#define ENABLE_RADIO_LINK "enable-radio-link"
#define ENABLE_TV_LINK "enable-tv-link"
framework.handle_config(ENABLE_RADIO_LINK)
framework.handle_config(ENABLE_TV_LINK)

I was thinking, it will simply make little bit more time to read code and cross reference what these #defines means.

Is it really a best practice, to #define(or static const whatever) them and use it even though it is used in one place?

what is the advantage of having this?

Sam Daniel
  • 1,800
  • 12
  • 22
  • 1
    If these strings only occur in one place, I would not predefine them as constants. – River Feb 16 '16 at 17:14
  • 2
    Preprocessor macros are [evil](http://stackoverflow.com/q/14041453/10077)! (for [certain definitions of evil](https://isocpp.org/wiki/faq/big-picture#defn-evil)) – Fred Larson Feb 16 '16 at 17:16

2 Answers2

3

I prefer

const std::string ENABLE_RADIO_LINK = "enable-radio-link";

instead of a macro because the compiler will be aware of the former, but not the latter. In other words, you will get more useful error and warning messages when the string is defined as a constant rather than a macro.

You can also wrap all these constants into a namespace, which is safer and probably easier to read. Example:

namespace FrameworkConsts {
    const std::string ENABLE_RADIO_LINK = "enable-radio-link";
    const std::string ENABLE_TV_LINK = "enable-tv-link";
    /*etc.*/
}

Then use them like this:

framework.handle_config(FrameworkConsts::ENABLE_RADIO_LINK);
Carlton
  • 4,217
  • 2
  • 24
  • 40
  • 3
    Note that this is no longer a compile-time constant. For that, you use `constexpr char ENABLE_RADIO_LINK[] = "enable-radio-link";` – Ben Voigt Feb 16 '16 at 17:26
  • 1
    Yes, I agree. When it comes to #define or static const, i would also prefer to use static const. But what is the real advantage of defining them and using.. – Sam Daniel Feb 16 '16 at 17:27
  • The advantage is that when you inevitably need to break your promises that the strings "will only be written in one place" and "won't be repeated anywhere else", it is much easier to manage their usage if they're defined in one place. Another, less-technical advantage is that most IDEs will recognize your constants and suggest them for auto-completion. – Carlton Feb 16 '16 at 17:32
  • And change the name so that it does not look like a macro anymore. – Christian Hackl Feb 16 '16 at 17:46
3

Since it's your own framework, a better idea to get the benefits of "only one place" would be to change out strings for an enum class. Each one of your defines will pollute the namespace and be visible to everyone who includes your header. This also provides compile-time checking on which flags are considered valid.

enum class MyConfiguration {
    EnableRadioLink,
    EnableTVLink
};

void enableConfig(MyConfiguration config) {
    // Do something with config
}

int main() {
    //...
    enableConfig(MyConfiguration::EnableRadioLink);
    enableConfig(MyConfiguration::EnableTVLink);
    //...
    return 0;
};
pyj
  • 1,489
  • 11
  • 19
  • well, we have to live with strings when it comes to our framework... But, Did you mean have enums in our code and when pass to framework convert enum to string? – Sam Daniel Feb 16 '16 at 17:50
  • The intent of an enum is to prevent you from passing illegal or incorrect values. It's a "put the square into the square hole" solution which gives you compile-time checks on ensuring you send valid values. If you're stuck with strings I'd probably just go with @Carlton's solution as enum class underlying type must be an integral type and a conversion function would be more code. – pyj Feb 16 '16 at 17:54