I am using C++11. I am not allowed to use external libraries like boost etc. I must use STL only.
I have a number of events, which must be identified as string const
In light of the fact that you're stuck with C++11, I think my suggestion from here still stands:
#ifndef INCLUDED_EVENT_NAMES
#define INCLUDED_EVENT_NAMES
#pragma once
namespace event_names
{
constexpr auto& event_1 = "event_1";
constexpr auto& event_2 = "event_2";
}
#endif
Defining named references to string literal objects is very simple, does not require any additional libraries, is guaranteed to not introduce any unnecessary objects, won't require any additional memory over the storage for the statically-allocated string literal objects that you'd need anyways, and will not have any runtime overhead.
If you could use C++17, I'd suggest to go with the std::string_view
approach, but in C++11, I think the above is most-likely a good compromise for your application.
The easiest way would be to use a char const*
constant, as it's way more optimizable and don't use dynamic allocations.
Also you can use std::string_view
in the postEvent
function, avoiding dynamic allocations. This step is optional. If you cannot have string views and still want to avoid dynamic allocations, then refer to your implementation's SSO max capacity and keep event names below that size.
Also consider that nonstd::string_view
can be shipped as a C++11 library and most likely the abstraction you need. Library such as cpp17_headers and string-view-lite exist solely for that purpose.
It look like this:
constexpr auto event_name1 = "event_name1";
In a class as a static member it works the same way:
struct Type {
static constexpr auto event_name1 = "event_name1";
};
This will at most take space in the read-only static data of your executable.
Global const std::string
has one drawback it need processing during startup and creates copy of string literal.
The linked SO answear uses constexpr std::string_view
and this is cool solution since constructor is constexpr
so nothing have to be done on startup. Also it doesn't create any copy. Problem is that this is C++17
Use of const char []
(or auto
or constexpr
) is old proven solution. You can compare std::string
with it without any extra overhead.
You can create header file for all that strings and let linker to remove all duplicates. It was working like that in old C++.
For the sake of proper abstraction and good design, you should define an event class. This event class will have either:
name()
or system_name()
)to_string()
freestanding function which takes such an event (not recommend)But beyond that - all of your class can now use an enum, or an index, or whatever they like - they'll just need to use the conversion method whenever they interact with whatever it is that requires strings. Thus none of your classes has to actually know about those strings itself.
The strings themselves can stay within the .cpp implementation file of the class, and nobody else has to know about them. (unles they are actually defined in code that's not yours, but that's not how you described the problem.)
You can have a struct of static strings:
struct MyNames
{
static const std::string name1;
};
And in a cpp:
const std::string MyNames::name1 = "foo";
You can then access the names from all your required locations. In C++17, you would have used string_view
instead to avoid object construction. But this seems to be a duplicate of this answer, basically: https://stackoverflow.com/a/55493109/2266772