Reputation: 21025
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 constants. I am not allowed to use enums or ints or any other data type. For example:
"event_name1"
"event_name2"
"some_other_event_name3"
"a_different_event_name12"
Then I have some classes which need to use these strings, but don't know the other classes exist (they don't have anything to do with each other).
class Panel{
void postEvent(){
SomeSingleton::postEvent("event_name");
}
}
Another class::
class SomeClass{
SomeClass(){
SomeSingleton::listenForEvent("event_name");
}
void receiveEvent(){
//This function is triggered when "event_name" occurs.
//Do stuff
}
}
All these events are constants, and are used to identify things that are happening.
Here is what I have tried:
How to store string constants that will be accessed by a number of different classes?
Some of the persons there suggested I provide specific details of how to solve a concrete problem, so I have created this new question.
How can I store the strings in a common file, so that all the other classes that use these strings can refer to the same file?
Upvotes: 4
Views: 492
Reputation: 15951
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.
Upvotes: 4
Reputation: 131978
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.)
Upvotes: 1
Reputation: 41780
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.
Upvotes: 8
Reputation: 38062
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++.
Upvotes: 3
Reputation: 22023
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
Upvotes: 2