I have a huge C++ solution created as a "win32 console application" project in MVS2008, the only Additional Options during the creation having been : "precompiled header".
In this solution I now have a huge amount of enums defined in various ways : they are always defined in a .h file, but they can be defined either within a namespace, either within a class, either within a class within a namespace.
I would like to define in more elegant way (I know how to do it in a bruteforce way, but it wouldn't be DRY, right ?) a function:
void myfunc( const char * )
Which would print all "stringed" values of an enum when I pass to it the "string value" of this enum.
To be precise, if I have somewhere in my code:
enum Place
{
Home,
Work
};
I would like to be able to pass to my function the string "Place", and my function to print the strings "Home" and "Work".
Having really A LOT of enums, I would like, if possible, to avoid modifying them a lot, ideally not at all. I thought of a small parser, but I don't think this optimal at all.
By the way, I am RESTRICTED not to use external things different from boost, but I can use macros. I would like to be able to somehow define the concepts of "loop" over enums, and of "loop within the "strings of enums"" as well, but don't see how to do it at all.
All ideas are welcome.
Related
In Java, I find it very straightforward to use namespaces. For each qualified identifier Ident I use in a source file, I put an import ns1.ns2.ns2.ns3.ns4.Ident; at the top of the file. Then I can use (short) unqualified names everywhere in my source code. The import statement cannot cause any problems, because it applies only to the file in which it is written down.
However, I'm not quite sure how to get rid of namespace qualifiers in C++ the best way.
The most obivous solution would probably be the using and using namespace statement. However, that seems to be a rather bad solution, at least in the case of header files, because the using statements are not restricted to the single file where they are written down. So using is ruled out in the case of e.g. slim libraries consisting only of header files with the implementions directly inside or in the case of header files in general.
Another option, which I use so far, is to add for each qualified name I use in a class a corresponding typedef in the private section of the class. So when comparing this approach to Java, I basically take the whole import statement list, replace the import with typedef and place it in the class declaration.
However, I don't really like this approach, because users of my classes - strictly speaking -don't know the types of return values and parameter values, because the types in the method declarations are private types of the corresponding classes.
OK, now we could make all this typedef stuff public. But that's probably a not so good idea, as we would redefine each type many many times. Just think of a struct ns1::ns2::ns3::MyStructure and two Classes MyClassA and MyClassB. Both classes have a method which actually should take as parameter an instance of ns1::ns2::ns3::MyStructure. But because every class redefines the types it uses to get rid of the long qualified names, the two methods now take parameters of "different" types, say MyClassA::MyStructure and MyClassB::MyStructure. It becomes even catchier when we have a third class MyClassC which works with an instance of MyStructure and need to call both methods with it. Should this class declare this instance with type MyClassA::MyStructure, MyClassB::MyStructure or MyClassC::MyStructure?
Well, what I simply want to know is: What is the best practise for getting rid of the namespace qualifiers?
Recently I've been taking a hard look at my programming style and how to improve it. Let me begin by saying that in my current role, I'm the sole programmer. As a result, I can make things as hacky as I want, but I'm really striving to become a better, more sound programmer.
Also, my background was mainly C based, with essentially using C++ as a super-set of C when necessary. As a result, I have stumbled across the following conundrum.
I have always defined error codes with something like #define ERROR_FUNCTION_BLEW_UP -2 . In honesty, I can see the benefits of doing so since I don't have to allocate the memory to store -2. However, in C++ I can see the benefit of using a const variable since there's less chances of collisions between two competing macros.
As a result, I was wondering what the cleanest way is to implement error codes in C++. Namely, I'd like to have the client be able to check the return value of certain functions by doing something analogous to "if (return_value == ERROR_FUNCTION_BLEW_UP)". I've tried adding a const variable in each class, but then the code doesn't look right. That is, the client now checks something along the lines of "if (return_value == MyClass.kErrorFunctionBlewUp_)". Is there a cleaner way of accomplishing this, rather than having the constant be a public member of the class?
Also, to add onto my question, myClass is a base class, and now I want to add more error codes in MyDerivedClass. What's the best way of going about this and avoiding macros?
Thank you all for your help.
Use enums:
enum Errors
{
NO_ERROR = 0,
FUNCTION_BLEW_UP,
WTF_THIS_SHOULDNT_HAPPEN,
};
Also, consider using exceptions (look into std::exception) if they're more appropriate.
If you really want to just replace your macros, replace them with a constant. A constant has internal linkage (i.e. restricted to the translation unit ("file")) so the compiler can easily replace their use with just the constant inline and without using a single byte more or less than for a macro. Note that it is customary to keep ALL_UPPERCASE to macros, because macros don't follow normal code conventions, so you'd have to change that, too.
Then, in C++, you don't generally use returncodes that the caller has to check but exceptions which propagate automatically. If you want to keep the errorcodes, you can use an enumeration or constants and put them into a namespace. Note that enumerations leak into the surrounding namespace or class, which makes it preferable to wrap them up one level:
namespace errorcode
{
enum type
{
printer_on_fire,
volume_not_formatted,
bluescreen
};
}
Exceptions do sometimes contain error codes that further specify what failed though. Here's one way to specify them:
struct error:
std::runtime_error
{
...
enum code
{
printer_on_fire,
volume_not_formatted,
bluescreen
};
code fault;
};
Note that you don't have to nest the code, you can also build the exception type with the existing errorcode::type above. Some nesting is useful though, because enumerations otherwise pollute the surrounding namespace.
That said, you ask "do I place it at the top of the file before the class", but here you have a misconception. Firstly, not every file contains a class. Then, not every file that contains a class contains exactly one of them. For example, if the collection of errorcodes is used by a whole class hierarchy it makes sense to define it in a separate file to make clear that it doesn't belong to just one of them and that it can be used in related non-class functions, too. In that file, you would also stick e.g. a function to convert it to a string for debugging and maybe the exception type carrying one of them.
The library offers a class to be derived from with the derived class as a template argument.
Example:
class userclass : public lib::superclass<userclass>
{}
As you can see its quite a lot to type. And the "userclass" should always derive as public for it to work correctly. So i came up with two MACROs looking like this:
#define SUPER(x) public lib::superclass<x>
#define SUPERCLASS(x) class x : public lib::superclass<x>
The user can now type either of.
class userclass : SUPER(userclass)
{}
SUPERCLASS(userclass)
{}
But the main problem is that the macros SUPER and SUPERCLASS exist in the users global namespace as quick as the header is included.
Can/should i:
Have a way of preserving the namespace requirement but still defaulting to public derives?
Use the macros as they are.
Simply require the user to write out the full "public lib::superclass".
I'm using vs 11 and the library is targeted against windows developers.
The first rule of using macros is "Don't, if there's any other solution". In this case, there is another solution, so get rid of them.
Secondly, your macros do way more harm than good, because people have no idea what they expand to by just reading it, whereas the full definition does. Seriously, you're saving a truly minute number of characters for a truly hideous cost in readability. It's far superior to simply write out the inheritance.
That really isn't a lot to type. I've seen a lot longer lines that shouldn't be shortened. Hiding it with a macro just obfuscates your code. If I take a quick look at your SUPERCLASS(userclass) {}, I can pretty much guess that it's a class (I don't like to use a library based on guesses) but I don't know if it or its parent is called userclass (or neither) or what kind of inheritance it's using. It means you have to document it and you force people to look it up when they need it.
So the correct answer is option 3 - don't use macros.
If you really really really need to use a macro in your library, give it a library specific prefix. That's as close as you'll get to a namespaced macro.
I vote for 3. Simply require the user to write out the full "public lib::superclass".
Macros in libraries may be useful if:
there is really a lot to write,
something has to be written several times
or you want to hide an ugly implementation detail and the language doesn't allow you to do otherwise.
But in your case:
not so much to write,
yes, you have to put the class name twice,
you do not want to hide the fact that you are subclassing, or even that you are writing a class!
I don't think that the duplication of the class name - the one positive point - is worth it. Particularly because you will hide the class keyword and cause quite some confusion on the reader.
Anyway, if a library uses macros it is customary to put the library name in front of all macros:
#define MY_FANCY_LIBRARY_NAME_SUPER(x) public lib::superclass<x>
But now you are not saving so much typing...
PS: Remember the golden rule of programming:
Code is written once but read forever, thus it should be easy to read, more than easy to write.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Static members class vs. normal c-like interface
I am looking at somebodies code and there are several dozen constants defined in a class like this:
// header file
class Defines
{
public:
static const int Val1;
static const int ValN;
static const char* String1;
static const char* StringN;
...
}
// .CPP
const char* Defines::String1 = "some value"
etc.
Is there some reason to do things this was as opposed to using a namespace instead?
Are there advantages/disadvantages of one over the other
--------- Edit ----------
I'm sorry, I obviously should have pointed this out explicitly, as nobody has inferred it from the name of the class - which is "Defines". i.e. these constants are not associated with a particular class, there has been a class created specifically just to hold constants and nothing else, that is all the class Defines contains.
My question is not why should you place constants in a particular class, the question is is there any value in collecting dozens of them together and placing them in a class whose only purpose is to collect together constants, as opposed to collecting them together in a namespace, or just collecting them together in a header file specifically for that purpose etc.
(There is no currently existing namespace in the project therefore potential issues of polluting the namespace as mentioned in answers are not relevant in this case.)
----- 32nd edit -----------
and a follow up question ---
is placing
const char* Defines::StringN = "Somevalue"
in the .h file inefficient versus placing it in the .cpp file?
Because those constants may be tightly coupled to that class. IE Maybe members of the class take those constants as arguments or return them. Maybe the only place they are meaningful is in the interface to this class, so putting them in a separate namespace doesn't make sense because they only matter to that class.
There is no reason to do it the way it is done here; just like there is not really a reason to use class Defines { public: ... }; instead of struct Defines { ... };. Perhaps whoever wrote the code had previously been writing in a language that does not support namespaces/global variables in namespaces, or thought that this looked `neater' than a lot of extern statements and a namespace.
There is some practical use for this, however, if you intend to make some of these constants private, and then give access to only a few functions/classes. From the looks of it, however, this isn't the case, and it would make sense to change this to be a namespace -- that way, one could use using Defines::constant; and similar.
Response to first edit: The global namespace is also a namespace, and it is more dangerous to pollute than other namespaces, as things are more likely to leak into it. In that sense, it is better to put the variables in a class, but still not as good as putting them in a namespace of their own.
Response to second edit: const char* Defines::StringN = "Somevalue"; in a header would lead to the constant being defined multiple times, and the program would fail to link. However, if you prepend an extern to that, and put the definition in a .cpp file, everything will be fine, and there should be no performance penalty.
For a few reasons:
You're not cluttering your namespace with potentially random constants.
You're adding meaning to both the class and the constants themselves by including them with their associated class.
If I were to define a global/namespace constant named NAME, then what is it associated with? If I added into the class itself, then you're forced to reference is with the class name, which adds meaning to the usage and makes the code more readable and less error prone.
Of course, this can be abused. You can misplace constants. You can improperly put truly global constants in specific classes. You can, in both cases, give bad names.
In general, there's no reason to use a type this way. I have seen it argued that if the "collection of constants" evolves into a concrete object, starting this way makes the transition easier. In practice, I've never seen this happen. It just hides intent, and potentially flutters the code with private constructors.
One could argue that classes work with templates, while namespaces do not. So something like the following would only work if Defines is a class:
template<typename T> int function() {
return T::x + T::y;
}
//later
cout << function<Defines>() << function<OtherDefines>() << endl;
In most cases, there's probably a redesign that would work better, particularly if all you have are "constants" that aren't really. Occasionally, this may come in handy, though.
At times, it can also fight argument dependent lookup. In brief, the compiler is allowed to expand it's search for eligable function names to different name namespaces based on the parameters passed to the function. This does not extend to static functions of a class. This applies more to the general case, though, where the "static class" also includes nested types and functions in addition to the collection of constants.
Why people do this varies. Some come from languages where can't be used this way, others just don't know any better.
For most things, it makes sense to give them the smallest scope possible. In this case its not so much an issue of visibility, but in clarity.
If you see String1 in a method, you have no idea where it came from. If you see Defines::String1, you can say "OK, this is a variable from the class Defines, let me go there and see what it is and what it's supposed to be". Looking in one class is a lot better than looking through an entire namespace that might even be spread across multiple source files. Obviously if the variable is in a class because its used primarily in that class, there's no doubt whatsoever that's that's where it should be. :D
Coming from a C# background from a night course at a local college, I've sort of started my way in C++. Having a lot pain getting used to the syntax. I'm also still very green when it comes to coding techniques.
From my WinMain function, I want to be able to access a variable which is using an enum I declared in another class.
(inside core.h)
class Core
{
public:
enum GAME_MODE
{
INIT,
MENUS,
GAMEPLAY
};
GAME_MODE gameMode;
Core();
~Core();
...OtherFunctions();
};
(inside main.cpp)
Core core;
int WINAPI WinMain(...)
{
... startup code here...
core.gameMode = Core.GAME_MODE.INIT;
...etc...
}
Basically I want to set that gameMode to the enum value of Init or something like that from my WinMain function. I want to also be able to read it from other areas.
I get the error...
expected primary-expression before '.' token
If I try to use core.gameMode = Core::GAME_MODE.INIT;, then I get the same error.
I'm not fussed about best practices, as I'm just trying to get the basic understanding of passing around variables in C++ between files. I'll be making sure variables are protected and neatly tucked away later on once I am use to the flexibility of the syntax.
If I remember correctly, C# allowed me to use Enums from other classes, and all I had to do was something like Core.ENUMNAME.ENUMVALUE.
I hope what I'm wanting to do is clear :\ As I have no idea what a lot of the correct terminology is.
Use
core.gameMode = Core::INIT;
The individual values of an enumeration are scoped not within that enumeration but at the same level as the enumeration itself. This is something that most other languages (including C#) do differently, and C++0x will allow both variants so that there,
core.gameMode = Core::GAME_MODE::INIT;
will also be legal.
In addition, the strongly typed enums that will be added in C++0x (enum class) will put the enum values only within the scope of the enum (i.e. as in C#); this solves the problem you noted in your comment that for "normal" enums, the identifiers for enum values need to be unique across all enums defined in the same scope.