Simple question, how do I shorten a call/name without using defines.
For example, I have a singleton that I have to call that is within a namespace (I cannot use using namespace blabla because it is not allowed) like so:
MyFW::GameRoot::Instance()->DoSomething();
Now I can assign that to a variable, which works somewhat if I am using it multiple times within the same class/function, but using it in many classes/functions it becomes cumbersome. I decided to use #define for it:
#define MyFW::GameRoot::Instance() ROOT //defined in GameRoot.h
ROOT->DoSomething(); //Used where-ever GameRoot.h is included
Much better, and I really like it especially because now wherever I see ROOT (color coded through V-Assist) I know what it is immediately... unless I have a breakpoint there and I need Visual Studio to resolve ROOT to show up in the watch window (or even hover over it to quickly pull up the object in debug), which it cannot do.
Is there any other option? What do you guys do to shorten names? Simply use local/member pointers to store the instance?
Thanks!
You can't use using namespace ..., but can you use
namespace root=MyFW::GameRoot;
Then you can type
root::Instance()->DoSomething();
Defining a namespace like that is better than a #define. (I.e it can't get munged up somewhere else by mistake. The compiler knows what you are trying to do.)
Use local references:
MyFW::GameRoot& ROOT = *MyFW::GameRoot::Instance();
Do not use defines.
If you want to ease access across multiple functions, just use a helper function:
namespace {
MyFW::GameRoot* root() { return MyFW::GameRoot::Instance(); }
}
// ...
root()->DoSomething();
Two characters more, but it with comes type-safety included.
The good way to do this (but never in a header) is
using MyFW::GameRoot;
GameRoot::Instance()->DoSomething;
This is a using declaration and is different from a using directive, which is what you mentioned above.
Related
I would like to evaluate an algorithm with an available public code in my project. I have integrated the files the algorithm needs into my project: kodtree.h, kodtree.cpp, pinpolyhedron.h, and pinpolyhedron.cpp. However, the compiler complains about the ambiguous symbols. I changed the variable names which were ambiguous to something else and the compiler compiles it with no problem. This way does not look like an elegant way of fixing the issue.
I was thinking of using namespace but found out that, for example, the file kodtree.h has several externs.
Would putting them into namespaces cause me trouble since they can contain extern?
Could someone kindly let me know the things I should be aware of when creating namespaces for such libraries?
Is using namespace the right way of doing this?
Or is it better to create an interface class for this library and put everything, i.e., kodtree.h, kodtree.cpp, pinpolyhedron.h, and pinpolyhedron.cpp, inside that class and make them private?
What is the recommended way of doing this?
I would appreciate any tips.
Is using namespace the right way of doing this?
Yes, but not the way you try to go about it. Libraries should properly namespace themselves, but sometimes they can't or won't for various reasons. It's best to leave them be, unless you intend to write a full blown wrapper around the library code.
We can always apply a little discipline and namespace our own code. Simply put, we can do something like this in every one of our own source files1:
#include <some_library.h>
#include <my_other_project_header.h>
namespace ProjectName { namespace ModuleName {
// Your code here
}}
That way your code is nicely insulated from whatever you include. And barring any extern "C" things, there should be no conflicts. Whatever the library header drags in, it will not cause clashes with code you write inside your namespaces. All the while, your code can refer to project entities with at most one level of qualification (code in Module1 can refer to Module2::Foo, or to Module1::Bar as simply Bar). Beyond that you can always refer to things outside your Project namespace by fully qualifying things or by employing using declarations.
1: If your compiler supports C++17, it can be the more palatable:
namespace ProjectName::ModuleName {
}
I'm using std in my code(using namespace std)(I know it's not so good & should be avoided) and then I wondered which names are available to be used for variables or functions and which are already occupied so I searched for the list of the std variables & functions but I didn't find it.
PS. my code is actually a homework so there is no expanding dream and also cause it's a homework I'm expected to use std ( :| )(and even if I'm not I'm just curious about the answer). so my problem is what are the vars & funcs that are existing in std right now.
There is no definitive list of names inside std - it can always be expanded, and was created exactly for that purpose. Therefore, stop using the namespace once and for all.
In other words, C++ standard prescribes what names have to be there, but by no means it limits the overall names set to those prescribed. Implementations often put a lot of other helper functions or classess into this namespace.
As the others suggested, stop using namespace std - this is bad practice.
I'd also suggest that you stop using any namespace. This way your code reads better, you avoid shadowing things and name clashes and, most importantly, you are always in charge of your codebase: you know where the things you use come from and what their broader scope/purpose may be. This can make your code more maintainable: for example it's easier to see what headers are not in use. what kind of functions are just auxillary/internal etc.
This is primarily a matter of taste, but I'd further suggest that you use namespaces or verbose descriptive names yourself (at least for those objects that don't have very short scope). All contemporary IDE's offer autocompletion so you won't even have to type this more than once. In my code I use things such as:
bool has_the_loader_finished;
bool should_the_program_quit;
void helper::setup::setup_animation();
all the time. This way a. I don't really need many comments in my code, most of the things are self-explanatory so I reserve comments only for special things and b. I'm sure that there will be no name clashes and c. I don't have to spent time trying to debug/refactor code where I no longer remember what things such as
int i;
bool flag;
void setup();
stand for..
There are of course cases where using is intuitive, such as:
using std::placeholders
ExampleFunction f = std::bind(&Object::hello, &instance,_1); // instead of std::placeholders::_1
using namespace std::chrono_literals;
auto halfmin = 30s; //instead of std::chrono_literals::30s
using ms = std::chrono::milliseconds; // this is an alias basically
Good practice, however, is to always a. restrict using to those particular things you plan to use, e.g.: using std::placeholders rather than using std b. use aliases or typedefs and c. limit the scope of using (and typedefs/aliases) as much as you can e.g.:
int someFunction() {
using namespace std;
// no more than a 20-30 lines of code here
}
or
// someSmallFile.cpp
using namespace std; // this is valid in the body of this file only
Finally, NEVER use using namespace in header files. This will expose the internals of this namespace to all translation units that include that file and without your clients necessarily knowing about it...
In our huge codebase, in one of the include files, we have the statement
using std::some_function
However, I want to "unuse" some_function and use another some_function. I cannot modify this header because most of the code base depends on it.
Is there a possibility to do so?
I don't think there is. You should place your function in a namespace and qualify its use:
namespace MyNamespace
{
void some_function();
}
//...
MyNamespace::some_function();
Of course, the best you can do is remove the using directive and fix the code - but I (sadly) do understand why this isn't always an option.
EDIT: Just maybe, the using directive isn't there because of lazyness, but someone actually wants you to think twice before implementing your own some_function.
Depends what you want the scope of the "unuse" to be.
If it's scoped (to your own namespace or even better to a function) then you can put using MyNamespace::some_function; in your scope.
If it's global scope then the author of the original header has overruled you - in effect they got to the name ::some_function first, and they've prevented you from usingit for anything else. They shouldn't have pulled a std function into the global namespace, but you just have to live with their error.
Assuming that you don't want to make the same mistake they made, you only want the "unuse" to apply to one source file, you're not putting it in global scope in a header yourself. In that case you could #define some_function MyNamespace::some_function, but I don't recommend it because readers/maintainers of the code won't expect to have to realise that a lower-case name is actually a macro.
If some_function is a function (not a class as in the title), and you're only dealing with one overload (for example void some_function(), then there's another ugly workaround. Add another parameter:
static void some_function(int) { MyNamespace::some_function(); }
Then you can call it as some_function(0) and get the MyNamespace version. But if you're going to type extra text (in this case 0) I should think you might as well do it the expected way: make that extra text be MyNamespace::, or just use a different name.
I'm a bit confused concerning proper usage of C++ namespaces. It is clear for me how they can help to avoid conflicts (name collision), but it is not clear anymore when it comes to the using keyword. I mean, suppose I have a part of my code that I put into a namespace, and create a class, say
namespace my
{
class vector { ... };
}
Of course, when I use it, I wouldn't like to type my::vector all the time, so I'd like using namespace my. However, I could eventually need something from the std namespace, and then I want using namespace std at the same time, but this will bring me back to the initial name collision problem.
I know that it is possible to "import" only the functionality that I need, like using std::set, but in this case it seems natural to import both the standard namespace std and my namespace completely as I'd use both of them all the time.
Does this mean that even when I use namespaces I should still think about giving non-common names to my types? Or is using namespace a mistake and I should always type my::vector instead? Thanks.
Well, I should probably clarify that it is more a question of readability than typing. Lots of :: everywhere look really weird to me. I know it's a question of taste and habits, but nevertheless.
Of course, when I use it, I wouldn't like to type my::vector all the time, so I'd like using namespace my. However, I could eventually need something from the std namespace, and then I want using namespace std at the same time, but this will bring me back to the initial name collision problem.
Yes, it would bring you back to the initial name collision problem. This is why you should use using namespace ...; directives sparingly, and only in source files, never in headers.
Does this mean that even when I use namespaces I should still think about giving non-common names to my types?
No, you shouldn't. Namespaces were invented precisely to avoid this.
Or is using namespace a mistake and I should always type my::vector instead?
You can, if you want to, use the using namespace ...; or using ...; directives until you get conflicts. This means that when you do have conflicts, you'll end up writing "unnatural" code by explicitly quallifying names in some places.
In practice, when you're dealing with short namespace names (i.e. std), you can just type them explicitly all the time. After a week or so, you won't even notice you're typing it anymore.
If your code uses both std::vector and my::vector, then always writing the names in full is the best option.
Why bother putting it in a namespace in the first place, if you are immediately opening up the namespace again? You could just as well have put the class in the global namespace!
It would also be very confusing for people who didn't notice the using directive at the top of your file, that vector isn't std::vector. That in itself is a reason for writing my::vector!
To me, seeing names like std::vector and std::list actually improves readability, because I immediately know what those names mean.
I am using two large libraries (GUI & network) and I can happily do
using namespace FirstLib;
using namespace SecondLib;
Except for 1 single class called Foobar where names clash.
I my code, I do not use FirstLib::Foobar. Is there a way to say "in my code, whenever you see Foobar, think SecondLib::Foobar ?
using namespace is evil! Namespaces were made to prevent such problems as you have! But that said, try:
using namespace FirstLib;
using namespace SecondLib;
using SecondLib::Foobar;
or even (for some compilers):
using namespace FirstLib;
using namespace SecondLib;
typedef SecondLib::Foobar Foobar;
It's strange nobody suggested to replace the full namespace use by the list of used class names. This solution is even in the C++faq (where I should have thought to look first).
If we cannot say
include all FirstLib, but remove SecondLib::Foobar
We can use using-declarations of the exact elements we need:
using FirstLib::Boids;
using FirstLib::Life;
// no using FirstLib::Foobar...
You've basically answered your own question. You must explicitly say which class you want to use, so you must do SecondLib::Foobar whenever you use that class.
You have to pick one of these namespaces and get rid of the 'using', and explicitly call out all the class names. C# has a way around this, but C++ does not afaik...
I don't think there's a way of excluding names. You either bring in the whole lot, or each one individually. Even when you bring in the whole lot, you can always disambiguate conflicting names by qualifying them fully.
However, you could use typedef to rename the offending class:
typedef Lib2::FooBar FooBaz;
And I guess, with a conflicting function, you could use a function pointer to "rename" the conflicting one.
I guess it's kind of a non-solution. I can understand the occasional motivation to use using declarations - sometimes there are indeed many different names that you'll use all over the place - but if just one is conflicting: be explicit. It would be confusing to anyone familiar with the libraries anyway, seeing that both namespaces are imported.
Also, using declarations respect scope: you can make one namespace visible in one function, but not the other namespace - assuming you don't even use it in that function.
Have you tried:
using SecondLib::Foobar;
?
If you load all elements from both namespace to current scope by use of using namespace directove:
using namespace FirstLib;
using namespace SecondLib;
and there is potential that some of the names in those namespace may clash, then you need to tell compiler explicitly which of the element you want to use, in current scope, by use of using declaration:
using SecondLib::Foobar;
As the C++ standard says:
7.3.3 The using declaration
1 A using-declaration introduces a
name into the declarative region in
which the using-declaration appears.
That name is a synonym for the name of
some entity declared elsewhere.
This line requests compiler to think SecondLib::Foobar whenever it sees Foobar for the rest of current scope in which the using declaration was used.
The using directive and declaration is very helpful, but they may cause problems as the one you're dealing with. So, it's a good idea to narrow use of any form of using to minimal scope possible. You can use the directive using namespace in scope of other namespace
namespace MyApp {
using namespace ::SecondLib;
}
or even a function. The same applies to using declaration. So, it's a good idea to narrow the scope of use of any of them:
void foo()
{
::SecondLib::Foobar fb;
}
It may seem tedious, but it is only when you type, though you most likely use intellisense-enabled editor, so cost is really small, but benefits are large - no confusions, readable code, no compilation issues.
It's also a very good idea to NOT to use using namespace in header scope. See Header files usage - Best practices - C++
My own tip: do use full qualification whenever you need to use any of these types