I am looking for naming conventions for typedef of lengthy collections definitions. We have some c++ code which used auto to get away with style murder, but we need to make this code compiling on a non c++11 compiler. We are looking to establish a convention for typedef of collections, which can become quite lengthy
For instance
typedef std::map<enum MyFirstEnum,enum MySecondEnum> map_enum2_by_enum1_t
typedef map_enum2_by_enum1_t::value_type vtype_map_enum2_by_enum1_t
typedef map_enum2_by_enum1_t::iterator map_iterator_enum2_by_enum1_t
There are so many nuances (iterator before t than at beginning, using type rather than t, ditching the prefix map, etc...) that half of the time you select one nuance, half of the time you select the other.
At the end no typedef look like the other.
typedef std::map<enum MyFirstEnum,enum MySecondEnum> map_enum2_by_enum1_t;
If there's no "big picture" name that better describes the mapping, then I'd suggest Enum2_By_Enum1 or Enum1_To_Enum2: both imply an associative container without the map bit, which is a bit too Hungarian for my taste, with all the same flaws (e.g. if you move to say unordered_map will you change it - if you remember - or leave it being misleading?).
typedef map_enum2_by_enum1_t::value_type vtype_map_enum2_by_enum1_t;
I can't imagine this being useful... I'd typically only typedef a map's value_type inside a template when the concrete value type is unknown (e.g. the map or value type is one of the template parameters) and the map has no special or exclusive significance such that its value_type can reasonably be typedefed as the template's value_type, and in that scenario the map will necessarily have some other higher-level name reflecting its role in the template instantiation.
In conclusion, I'd omit this if at all possible and use enum2/MyFirstEnum directly.
typedef map_enum2_by_enum1_t::iterator map_iterator_enum2_by_enum1_t;
There's no reason for this unless the typedef identifier is significantly shorter than what it aliases. Just use <mapname>::iterator.
If you think you've got specific examples of code that's improved by having these last two typedefs, please share it.
All this is obviously subjective. That said, I tend to use a namespace to separate/isolate types, and keep names small/short:
enum foo_result;
enum bar_state;
enum baz_values;
namespace mappings { // namespace name tells you what's inside, so there is
// no need to call names inside with "map_" prefix
// "associate foo_result to bar_state"
typedef std::map<foo_result,bar_state> foo_result2bar_state;
// "associate foo_result to baz_values"
typedef std::map<foo_result,baz_values> foo_result2baz_values;
// I would not define these here:
// typedef foo_result2bar_state::value_type
// foo_result2bar_state_value_type;
}
Client code then becomes self-descriptive:
void f(mappings::foo_result2bar_state& m) // foo_result2bar_state is a "mapping" of types
{
// I prefer to have this alias in client code (i.e. where I use it)
typedef mappings::foo_result2bar_state::iterator itr;
itr begin = m.begin();
// ...
}
There are all sorts of ways.
Usually, I would aim to avoid the problem from the beginning, by deriving the typenames from the top level design rather than from types used to implement it. From a top level perspective, there is usually some concept that a type represents, and that concept is usually a suitable name - right from early design. Retrofitting things like type names onto existing sloppy code is really a bad idea.
But, given that this is your starting point, I suggest not being too lavish in adorning the names and do something like this.
namespace <libname>_Type
{
typedef std::map<FirstEnum, SecondEnum> map_first_second;
typedef map_first_second::value_type map_first_second_value;
typedef map_first_second::iterator map_first_second_iterator;
typedef map_first_second::const_iterator map_first_second_const_iterator;
}
or (if your library has its own namespace)
namespace <libname>
{
namespace Type
{
typedef std::map<FirstEnum, SecondEnum> map_first_second;
typedef map_first_second::value_type map_first_second_value;
typedef map_first_second::iterator map_first_second_iterator;
typedef map_first_second::const_iterator map_first_second_const_iterator;
}
}
Now, okay, the use of namespaces may make mean a bit more work to set up, but using the types is easier.
for (<libname>::Type::map_first_second_iterator i, end = some_map.end();
i != end;
++i)
{
do_something(i);
}
which can be simplified to avoid all the scoping with a judicious using.
If your style guidelines allow or require, it is possible to avoid use of underscore by using camel-case (e.g. instead of map_first_second_iterator use MapFirstSecondIterator. The key, for developers, is being consistent in using your naming conventions and not over-complicating it, rather than having a perfect one.
Related
Apologies in advanced if this is the wrong site, please let me know if it is!
I've written a function that checks to see whether a key exists in a particular std::map and wondered if this is a good practise to use, and, whether or not anyone can throw any pointers on improvements.
The std::map allows for multiple data-types to be accepted for the value.
union Variants {
int asInt;
char* asStr;
Variants(int in) { asInt = in; }
Variants() { asInt = 0;}
Variants(char* in) { asStr = in; }
operator int() { return asInt; }
operator char*() { return asStr; }
};
template<typename T, typename Y>
bool in_map(T value, std::map<T, Y> &map)
{
if(map.find(value) == map.end()) {
return false;
}else{
return true;
}
}
And I can then use in main the following:
std::map<string, Variants> attributes;
attributes["value1"] = 101;
attributes["value2"] = "Hello, world";
if(in_map<std::string, Variants>("value1", attributes))
{
std::cout << "Yes, exists!";
}
Any help or advise would be greatly appreciated. Sorry if this doesn't comply to the rules or standards. Thanks!
The biggest problem I see with your function is that you're throwing away the resulting iterator.
When you're checking if a key exists in a map, most of the time you want to retrieve/use the associated value after that. Using your function in that case forces you to do a double lookup, at the cost of performance. I would just avoid the use of the function altogether, and write the tests directly, keeping the iterator around for later use in order to avoid useless lookups:
auto it = map_object.find("key");
if (it != map_object.end())
use(it->second);
else
std::cout << "not found" << std::endl;
Of course if you're just checking whether a key exists and don't care for the associated value then your function is fine (taking into account what others told you in the comments) but I think its use cases are quite limited and not really worth the extra function. You could just do:
if (map_object.find("key") != map_object.end())
std::cout << "found, but I don't care about the value" << std::endl;
ny pointers on improvements.
sure.
template<typename T, typename Y>
bool in_map(T value, const std::map<T, Y> &map)
{
return map.find(value) != map.end();
}
And I'd place map as 1st parameter (just a preference). Also, because the whole thing fits into single line, you might not even need this function.
You're also throwing away returned iterator, but since you aren't using it, that's not a problem.
Apart from this, does this look ok in terms of coding practise? I.e. Using Union or are there other types I can use such as struct?
Well, using char* doesn't looke like a good idea, because char* implies that you can modify data. char* also implies that this pointer is dynamically allocated and you might want to delete[] that pointer later. And you can't use destructors in unions. If the text cannot be changed, you could use const char*, otherwise you might want to use different datatype. Also see Rule of Three
Next problem - you're trying to place char* and int at the same location. That implies that at some point you're trying to convert pointer to integer. Which is a bad idea, because on 64bit platform pointer might not fit into int, and you'll get only half of it.
Also, if you're trying to store multiple different values in the same variable, you are not indicating which type is being stored anywhere. To do that you would need to enclose union into struct and add field (into struct) that indicates type of stored object. In this case, however, you'll end up reinventing the wheel. So if you're trying to store "universal" type, you might want to look at Boost.Any, Boost.Variant or QVariant. All of those require BIG external libraries, though (either boost or Qt).
Typing
if(in_map<std::string, Variants>("value1", attributes))
seems a bit excessive to me, typing all of that typename syntax makes me want to just use the map.find function instead just out of convenience. However, depending on your compiler, sometimes the template parameters can be interpreted automatically, for example, visual studio will allow this:
if(in_map(std::string("value1"), attributes))
In this case, I had to construct an std::string object to replace the char*, but I've completely removed the template definition from the call, the compiler still figures out what T and Y are based on the parameters given.
However, my recommended advice would be to use #define to define your "function". While it is not really a function, since #define actually just replaces snippets of code directly into the source, it can make things much easier and visually appealing:
#define in_map(value,map) (map.find(value) != map.end())
Then your code to use it would just look like this:
if(in_map("value1", attributes))
You both get the optimization of not using a function call, and the visual appearance like it does in PHP.
I want to create a container (preferably map) that holds values of discrete type:
KEY Value
Omega 1.9
Output myoutput.out
sizex 82
##### ###
where the key is = "std::string" and the value is either of "INT/ DOUBLE/ String"
I tried declaring something like.
template<typename T>
map<string, typename T> mymap;
But sure it doesn't works.
:(
I know that there is simple way, splitting them into different variables but that just results in code bloat. Also I am clear about the fact,
std::map<key_value key, class Allocator = allocator<pair<const Key,T>>
needs to know information about "key" and "value" to generate space during compilation.
But this problem is bugging me for quite a while and just need to sort it :D
Can someone walk me through this :D
#include <map>
using namespace std;
union mytypes_t {
int c;
double i;
char* c;
}
int main()
{
Map<int, mytypes_t> myObject;
}
More on unions
The simple solution, as you mentioned is separating the data into three different arrays and writing a wrapper that will find the element in the appropriate container (assuming that the code that performs the lookup does know the type of the variable, else even this becomes complicated).
Alternatively you can use a variant type (boost variant) or type erasure (boost any) to use a container that will handle the different types. If you cannot use boost, implementing some simple type erasure is not that complicated, but I would stay away from it unless you really need it (i.e. prefer a pre canned over-the-shelf solution to your own square wheel)
I feel like I'm unprofessional in the way I name and use iterators. What I mean by that is that I "feel" like I should be calling them something else, but I always name them based on the "it_" prefix, and after a while, in a long function, the names start to all look alike.
Additionally, I always wonder if I'm doing things a "strange" way that I learned just because I didn't know better. For instance, if I were iterating through a map to display all its key/value pairs, I would do this:
map<int, int>::const_iterator it = layout.begin();
for (; it != layout.end(); ++it)
{
cout << it->first << ":\t" << it->second << "\n";
}
I see some people calling their iterators "iter" - I see other ways of doing loops. Is there any kind of convention that transcends style and is just good practice?
I try to declare the iterators inside the for loop as much as possible, so that the scope of the iterator identifier is minimized.
First, I typedef the "long" type names to "shorter" and re-usable ones:
typedef std::map< int, int > IntMap;
typedef IntMap::const_iterator IntMapConstIter;
Then, I do
for( IntMapConstIter it = layout.begin(); it != layout.end(); ++it ) {
....
}
I do that as follows
for (map<int, int>::const_iterator it = layout.begin();
it != layout.end(); ++it)
{
cout << it->first << ":\t" << it->second << "\n";
}
Thanks to that the iterator is scoped only inside the block, which makes it safer to give it a shorter name.
I am pretty sure no convention transcends style for this matter. I believe the most important part of iterator naming is on the second part (considering you decide to add a prefix, should it be "it" or "iter_" or anything else). Choose the second part carefully as you would for any other variable and you'll be fine.
I haven't seen a single canonical loop.
The cost of creating an iterator is specified to be O(1) (wrt the size of the container), but it may cost, especially when specific debugging options are activated.
Therefore, calling end at each iteration of the loop is wasteful.
The canonical way to write a for loop is therefore to compute both it and end in the first statement.
typedef std::map<int,int> LayoutType;
for (LayoutType::const_iterator it = layout.begin(), end = layout.end();
it != end; ++it)
{
// ...
}
I usually typedef my container, but honestly there isn't much point in typedefing the iterator, it's already available within the container and introducing too many synonyms does not help.
Also, it may be a personal quirk, but I prefer stating the function rather than the type when I introduce my typedef. The type may change in later refactoring, the function will not (at least, it won't be the same thing at all if it does, so it'll call for a complete rewrite).
For example what if you suddenly preferred: typedef std::unordered_map<int,int> LayoutType ? It still matches your need, and you can probably drop it in at no rewriting cost (providing you have used a typedef).
Would it be totally unreasonable for me to suggest the use of BOOST_FOREACH and for you to (mostly) forget about iterators ?
The name is the least important thing to me as long as it's clear and chosen appropriately.
This falls into the endless debate of variable naming
m_ for members
trailing underscore for members
etc...
I'm trying to get my head around tuples (thanks #litb), and the common suggestion for their use is for functions returning > 1 value.
This is something that I'd normally use a struct for , and I can't understand the advantages to tuples in this case - it seems an error-prone approach for the terminally lazy.
Borrowing an example, I'd use this
struct divide_result {
int quotient;
int remainder;
};
Using a tuple, you'd have
typedef boost::tuple<int, int> divide_result;
But without reading the code of the function you're calling (or the comments, if you're dumb enough to trust them) you have no idea which int is quotient and vice-versa. It seems rather like...
struct divide_result {
int results[2]; // 0 is quotient, 1 is remainder, I think
};
...which wouldn't fill me with confidence.
So, what are the advantages of tuples over structs that compensate for the ambiguity?
tuples
I think i agree with you that the issue with what position corresponds to what variable can introduce confusion. But i think there are two sides. One is the call-side and the other is the callee-side:
int remainder;
int quotient;
tie(quotient, remainder) = div(10, 3);
I think it's crystal clear what we got, but it can become confusing if you have to return more values at once. Once the caller's programmer has looked up the documentation of div, he will know what position is what, and can write effective code. As a rule of thumb, i would say not to return more than 4 values at once. For anything beyond, prefer a struct.
output parameters
Output parameters can be used too, of course:
int remainder;
int quotient;
div(10, 3, "ient, &remainder);
Now i think that illustrates how tuples are better than output parameters. We have mixed the input of div with its output, while not gaining any advantage. Worse, we leave the reader of that code in doubt on what could be the actual return value of div be. There are wonderful examples when output parameters are useful. In my opinion, you should use them only when you've got no other way, because the return value is already taken and can't be changed to either a tuple or struct. operator>> is a good example on where you use output parameters, because the return value is already reserved for the stream, so you can chain operator>> calls. If you've not to do with operators, and the context is not crystal clear, i recommend you to use pointers, to signal at the call side that the object is actually used as an output parameter, in addition to comments where appropriate.
returning a struct
The third option is to use a struct:
div_result d = div(10, 3);
I think that definitely wins the award for clearness. But note you have still to access the result within that struct, and the result is not "laid bare" on the table, as it was the case for the output parameters and the tuple used with tie.
I think a major point these days is to make everything as generic as possible. So, say you have got a function that can print out tuples. You can just do
cout << div(10, 3);
And have your result displayed. I think that tuples, on the other side, clearly win for their versatile nature. Doing that with div_result, you need to overload operator<<, or need to output each member separately.
Another option is to use a Boost Fusion map (code untested):
struct quotient;
struct remainder;
using boost::fusion::map;
using boost::fusion::pair;
typedef map<
pair< quotient, int >,
pair< remainder, int >
> div_result;
You can access the results relatively intuitively:
using boost::fusion::at_key;
res = div(x, y);
int q = at_key<quotient>(res);
int r = at_key<remainder>(res);
There are other advantages too, such as the ability to iterate over the fields of the map, etc etc. See the doco for more information.
With tuples, you can use tie, which is sometimes quite useful: std::tr1::tie (quotient, remainder) = do_division ();. This is not so easy with structs. Second, when using template code, it's sometimes easier to rely on pairs than to add yet another typedef for the struct type.
And if the types are different, then a pair/tuple is really no worse than a struct. Think for example pair<int, bool> readFromFile(), where the int is the number of bytes read and bool is whether the eof has been hit. Adding a struct in this case seems like overkill for me, especially as there is no ambiguity here.
Tuples are very useful in languages such as ML or Haskell.
In C++, their syntax makes them less elegant, but can be useful in the following situations:
you have a function that must return more than one argument, but the result is "local" to the caller and the callee; you don't want to define a structure just for this
you can use the tie function to do a very limited form of pattern matching "a la ML", which is more elegant than using a structure for the same purpose.
they come with predefined < operators, which can be a time saver.
I tend to use tuples in conjunction with typedefs to at least partially alleviate the 'nameless tuple' problem. For instance if I had a grid structure then:
//row is element 0 column is element 1
typedef boost::tuple<int,int> grid_index;
Then I use the named type as :
grid_index find(const grid& g, int value);
This is a somewhat contrived example but I think most of the time it hits a happy medium between readability, explicitness, and ease of use.
Or in your example:
//quotient is element 0 remainder is element 1
typedef boost:tuple<int,int> div_result;
div_result div(int dividend,int divisor);
One feature of tuples that you don't have with structs is in their initialization. Consider something like the following:
struct A
{
int a;
int b;
};
Unless you write a make_tuple equivalent or constructor then to use this structure as an input parameter you first have to create a temporary object:
void foo (A const & a)
{
// ...
}
void bar ()
{
A dummy = { 1, 2 };
foo (dummy);
}
Not too bad, however, take the case where maintenance adds a new member to our struct for whatever reason:
struct A
{
int a;
int b;
int c;
};
The rules of aggregate initialization actually mean that our code will continue to compile without change. We therefore have to search for all usages of this struct and updating them, without any help from the compiler.
Contrast this with a tuple:
typedef boost::tuple<int, int, int> Tuple;
enum {
A
, B
, C
};
void foo (Tuple const & p) {
}
void bar ()
{
foo (boost::make_tuple (1, 2)); // Compile error
}
The compiler cannot initailize "Tuple" with the result of make_tuple, and so generates the error that allows you to specify the correct values for the third parameter.
Finally, the other advantage of tuples is that they allow you to write code which iterates over each value. This is simply not possible using a struct.
void incrementValues (boost::tuples::null_type) {}
template <typename Tuple_>
void incrementValues (Tuple_ & tuple) {
// ...
++tuple.get_head ();
incrementValues (tuple.get_tail ());
}
Prevents your code being littered with many struct definitions. It's easier for the person writing the code, and for other using it when you just document what each element in the tuple is, rather than writing your own struct/making people look up the struct definition.
Tuples will be easier to write - no need to create a new struct for every function that returns something. Documentation about what goes where will go to the function documentation, which will be needed anyway. To use the function one will need to read the function documentation in any case and the tuple will be explained there.
I agree with you 100% Roddy.
To return multiple values from a method, you have several options other than tuples, which one is best depends on your case:
Creating a new struct. This is good when the multiple values you're returning are related, and it's appropriate to create a new abstraction. For example, I think "divide_result" is a good general abstraction, and passing this entity around makes your code much clearer than just passing a nameless tuple around. You could then create methods that operate on the this new type, convert it to other numeric types, etc.
Using "Out" parameters. Pass several parameters by reference, and return multiple values by assigning to the each out parameter. This is appropriate when your method returns several unrelated pieces of information. Creating a new struct in this case would be overkill, and with Out parameters you emphasize this point, plus each item gets the name it deserves.
Tuples are Evil.
I have an array of constant data like following:
enum Language {GERMAN=LANG_DE, ENGLISH=LANG_EN, ...};
struct LanguageName {
ELanguage language;
const char *name;
};
const Language[] languages = {
GERMAN, "German",
ENGLISH, "English",
.
.
.
};
When I have a function which accesses the array and find the entry based on the Language enum parameter. Should I write a loop to find the specific entry in the array or are there better ways to do this.
I know I could add the LanguageName-objects to an std::map but wouldn't this be overkill for such a simple problem? I do not have an object to store the std::map so the map would be constructed for every call of the function.
What way would you recommend?
Is it better to encapsulate this compile time constant array in a class which handles the lookup?
If the enum values are contiguous starting from 0, use an array with the enum as index.
If not, this is what I usually do:
const char* find_language(Language lang)
{
typedef std::map<Language,const char*> lang_map_type;
typedef lang_map_type::value_type lang_map_entry_type;
static const lang_map_entry_type lang_map_entries[] = { /*...*/ }
static const lang_map_type lang_map( lang_map_entries
, lang_map_entries + sizeof(lang_map_entries)
/ sizeof(lang_map_entries[0]) );
lang_map_type::const_iterator it = lang_map.find(lang);
if( it == lang_map.end() ) return NULL;
return it->second;
}
If you consider a map for constants, always also consider using a vector.
Function-local statics are a nice way to get rid of a good part of the dependency problems of globals, but are dangerous in a multi-threaded environment. If you're worried about that, you might rather want to use globals:
typedef std::map<Language,const char*> lang_map_type;
typedef lang_map_type::value_type lang_map_entry_type;
const lang_map_entry_type lang_map_entries[] = { /*...*/ }
const lang_map_type lang_map( lang_map_entries
, lang_map_entries + sizeof(lang_map_entries)
/ sizeof(lang_map_entries[0]) );
const char* find_language(Language lang)
{
lang_map_type::const_iterator it = lang_map.find(lang);
if( it == lang_map.end() ) return NULL;
return it->second;
}
There are three basic approaches that I'd choose from. One is the switch statement, and it is a very good option under certain conditions. Remember - the compiler is probably going to compile that into an efficient table-lookup for you, though it will be looking up pointers to the case code blocks rather than data values.
Options two and three involve static arrays of the type you are using. Option two is a simple linear search - which you are (I think) already doing - very appropriate if the number of items is small.
Option three is a binary search. Static arrays can be used with standard library algorithms - just use the first and first+count pointers in the same way that you'd use begin and end iterators. You will need to ensure the data is sorted (using std::sort or std::stable_sort), and use std::lower_bound to do the binary search.
The complication in this case is that you'll need a comparison function object which acts like operator< with a stored or referenced value, but which only looks at the key field of your struct. The following is a rough template...
class cMyComparison
{
private:
const fieldtype& m_Value; // Note - only storing a reference
public:
cMyComparison (const fieldtype& p_Value) : m_Value (p_Value) {}
bool operator() (const structtype& p_Struct) const
{
return (p_Struct.field < m_Value);
// Warning : I have a habit of getting this comparison backwards,
// and I haven't double-checked this
}
};
This kind of thing should get simpler in the next C++ standard revision, when IIRC we'll get anonymous functions (lambdas) and closures.
If you can't put the sort in your apps initialisation, you might need an already-sorted boolean static variable to ensure you only sort once.
Note - this is for information only - in your case, I think you should either stick with linear search or use a switch statement. The binary search is probably only a good idea when...
There are a lot of data items to search
Searches are done very frequently (many times per second)
The key enumerate values are sparse (lots of big gaps) - otherwise, switch is better.
If the coding effort were trivial, it wouldn't be a big deal, but C++ currently makes this a bit harder than it should be.
One minor note - it may be a good idea to define an enumerate for the size of your array, and to ensure that your static array declaration uses that enumerate. That way, your compiler should complain if you modify the table (add/remove items) and forget to update the size enum, so your searches should never miss items or go out of bounds.
I think you have two questions here:
What is the best way to store a constant global variable (with possible Multi-Threaded access) ?
How to store your data (which container use) ?
The solution described by sbi is elegant, but you should be aware of 2 potential problems:
In case of Multi-Threaded access, the initialization could be skrewed.
You will potentially attempt to access this variable after its destruction.
Both issues on the lifetime of static objects are being covered in another thread.
Let's begin with the constant global variable storage issue.
The solution proposed by sbi is therefore adequate if you are not concerned by 1. or 2., on any other case I would recommend the use of a Singleton, such as the ones provided by Loki. Read the associated documentation to understand the various policies on lifetime, it is very valuable.
I think that the use of an array + a map seems wasteful and it hurts my eyes to read this. I personally prefer a slightly more elegant (imho) solution.
const char* find_language(Language lang)
{
typedef std::map<Language, const char*> map_type;
typedef lang_map_type::value_type value_type;
// I'll let you work out how 'my_stl_builder' works,
// it makes for an interesting exercise and it's easy enough
// Note that even if this is slightly slower (?), it is only executed ONCE!
static const map_type = my_stl_builder<map_type>()
<< value_type(GERMAN, "German")
<< value_type(ENGLISH, "English")
<< value_type(DUTCH, "Dutch")
....
;
map_type::const_iterator it = lang_map.find(lang);
if( it == lang_map.end() ) return NULL;
return it->second;
}
And now on to the container type issue.
If you are concerned about performance, then you should be aware that for small data collection, a vector of pairs is normally more efficient in look ups than a map. Once again I would turn toward Loki (and its AssocVector), but really I don't think that you should worry about performance.
I tend to choose my container depending on the interface I am likely to need first and here the map interface is really what you want.
Also: why do you use 'const char*' rather than a 'std::string'?
I have seen too many people using a 'const char*' like a std::string (like in forgetting that you have to use strcmp) to be bothered by the alleged loss of memory / performance...
It depends on the purpose of the array. If you plan on showing the values in a list (for a user selection, perhaps) the array would be the most efficient way of storing them. If you plan on frequently looking up values by their enum key, you should look into a more efficient data structure like a map.
There is no need to write a loop. You can use the enum value as index for the array.
I would make an enum with sequential language codes
enum { GERMAN=0, ENGLISH, SWAHILI, ENOUGH };
The put them all into array
const char *langnames[] = {
"German", "English", "Swahili"
};
Then I would check if sizeof(langnames)==sizeof(*langnames)*ENOUGH in debug build.
And pray that I have no duplicates or swapped languages ;-)
If you want fast and simple solution , Can try like this
enum ELanguage {GERMAN=0, ENGLISH=1};
static const string Ger="GERMAN";
static const string Eng="ENGLISH";
bool getLanguage(const ELanguage& aIndex,string & arName)
{
switch(aIndex)
{
case GERMAN:
{
arName=Ger;
return true;
}
case ENGLISH:
{
arName=Eng;
}
default:
{
// Log Error
return false;
}
}
}