Is it possible to detect whether at a given point of code you are in a namespace? In particular, I want to include a warning if a file is being including in the global namespace.
I can give you a hint that generates compilation error if header is not include in global namespace. If I know C++ constructiom which for sure generates compiler warning (other that #warning) then it could be used instead of compilation error.
Put in your header:
template <class A, class B>
struct AreSame { enum { VALUE = -1 }; };
template <class A>
struct AreSame<A,A> { enum { VALUE = 1 }; };
struct TestGlobalNamespace
{
int test_namespace[AreSame<TestGlobalNamespace, ::TestGlobalNamespace>::VALUE];
};
When your header is include in some namespace you'll get an error.
Like in this example:
namespace Some {
struct TestGlobalNamespace
{
int test_namespace[AreSame<TestGlobalNamespace, ::TestGlobalNamespace>::VALUE];
};
}
You'll get:
prog.cpp:17: error: size of array ‘test_namespace’ is negative
[UPDATE]
However the more probably would be this kind of errors:
prog.cpp:17: error: ‘::TestGlobalNamespace’ has not been declared
prog.cpp:17: error: template argument 2 is invalid
Anyway - no one will dare to include your header to namespace other than global.
Good practice is including all headers in global namespace. Open all needed namespaces at the beginning of file and close them before end. Another way will inevitably lead to heap of problems.
** Comment extension **
To prevent unintended inclusion, you can do something like this:
In header:
#ifndef INTERNAL_INCLUDE
#error ...
#endif
When used:
#define INTERNAL_INCLUDE
#include "internal.h"
#undef INTERNAL_INCLUDE
You can do this with the small inconvenience of requiring a second header, to be included in the global namespace before the first.
// stuff_guard.h - include from global namespace to guard stuff.h
#ifndef STUFF_GUARD_H
#define STUFF_GUARD_H
typedef char stuff_guard[1];
#endif
// stuff.h - must be included from non-global namespace, after stuff_guard.h
// No include guard - may be included multiple times, in different namespaces.
#ifndef STUFF_GUARD_H
#error stuff_guard.h must be included before stuff.h
#endif
typedef char stuff_guard[2];
static_assert(sizeof (stuff_guard) != sizeof (::stuff_guard),
"stuff.h must not be included from the global namespace");
// Put your stuff here
This will give reasonably friendly error messages if you break either of these two rules, and a somewhat less friendly error if you include stuff_guard.h from a non-global namespace.
If you're stuck with an old compiler and static_assert isn't available, then you could use BOOST_STATIC_ASSERT, or roll your own.
Related
I am currently working on a project where we have a shared set of headers. Now we want add some private fields without having to put those declarations directly in the shared headers.
Someone brought up the following:
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
Inside the _private.hpp headers we would then place the private fields for that class. When there are only default datatypes (int, bool, etc) this works fine(ish). But as soon as you put an include inside the _private.hpp file, for example #include everything breaks.
It is giving the following error expected unqualified-id before ‘namespace’ which as I understand is quite logical, since you're trying to define a namespace inside of a class.
Example _private.hpp file
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Now my question is, is there any way to trick the preprocessor, or somehow get the same results with a different solution?
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#if __has_include("foo_private.hpp")
#include "foo_private.hpp"
#endif
};
}
If that code is including a file that looks like this:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
Then you end up with this (though in reality, the #includes themselves would resolve to the contents of <string>, etc.):
namespace something {
class Foo {
public:
Foo();
void doFoo();
private:
#ifndef DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#define DUMMY_PRIVATE_TEMPLATE_INCLUDES_FOO_PRIVATE_HPP
#include <string>
int mySecretNumber;
std::string mySecretString;
#endif
};
}
Perhaps that shows your issue? You're including "string" in the middle of your class, but it needs to be included at the global namespace scope of your file.
Instead, include string at the top of the outer header, don't use include guards in the private header, and only put the body of the code you want pasted into your class into that private header. For that reason, you might not call it a ".hpp" file but something else to make it clear it's not a normal header.
Additionally, the __has_include feature seems dubious, because if your private header is missing you probably do not want it to compile to an empty class.
Worse, if you compile some translation unit that finds the header, and then compile another translation unit that does not find the private header, you will end up with two different definitions of your class, violating the One Definition Rule -- which is undefined behavior, no diagnostic required. Really nasty stuff (assuming your builds succeeds at all.)
I'm not a big fan of this kind of hiding, as it will make it hard for editors to properly show your code, to colorize and index your private header, or otherwise work with the code in a normal way. You might consider looking at the PIMPL idiom for hiding the implementation of a class in its .cpp file, so users of the header do not have to see it at all.
When compiling my code, I'm receiving many different errors such as:
frame.h:5:48: error: expected identifier before '(' token
frame.h:5:17: error: variable or field 'writeFrame' declared void
frame.h:5:17: error: 'GifWriter' was not declared in this scope
frame.h:5:34: error: expected primary-expression before 'double'
These errors more or less apply for all the function parameters.
Here is the header file:
#ifndef frame_h
#define frame_h
void writeFrame(GifWriter* gptr, double delay, (std::vector<uint8_t>& frameOut), ImageData* image1ptr, struct Options mode, int frameNum, bool* runptr);
void runPRGM(ImageData* image1ptr, struct Options mode);
#endif
My .cpp file does include the required libraries and this .h file, and the two functions are declared in the same way. I'm certain the brackets and parentheses are parsed correctly. Other than the function definitions within the .cpp, these are the only instances of the functions' declarations.
What could I potentially be doing wrong? I did read in some other thread that g++ conflicts with certain void functions as well but there wasn't much elaboration on that.
Change (std::vector<uint8_t>& frameOut) to std::vector<uint8_t>& frameOut.
Not sure why you felt the need to put the brackets there, and the first error message is telling you that's the problem.
Also note that you should write header files so that they are self-contained. This means that this header file should have #include <vector> as well as having declarations for GifWriter etc. These may be forward declarations if the circumstances are right.
So the header should look something like this
#ifndef frame_h
#define frame_h
#include <vector> // for vector
#include <cstdint> // for uint8_t
class GifWriter; // forward declarations
class ImageData;
struct Options;
void writeFrame(GifWriter* gptr, double delay, std::vector<uint8_t>& frameOut, ImageData* image1ptr, Options mode, int frameNum, bool* runptr);
void runPRGM(ImageData* image1ptr, Options mode);
#endif
Image assuming that GifWriter, ImageData and Options are classes that you have written and therefore its safe to forward declare them. If not then you should include the header files for those classes here instead.
I'm getting crazy since i'm not able to define the prototype of a function i'm actually using.
What i'm doing is create an header file called func1.hwhere i define this prototype (that's because i need to invoke this function from some other function implemented elsewhere):
void FileVector(std::vector<Files> &,const char*,bool);
Where Filesis a struct defined in func1.cpp
struct Files{
HANDLE h;
WIN32_FIND_DATA info;
} file;
I have also another function that accept a std::vector<Files> & as input parameter but when i try to compile (using Eclipse C++) i'm getting those errors:
/FileVector.h:11:22: error: variable or field 'FileVector' declared void
..\/FileVector.h:11:17: error: 'vector' is not a member of 'std'
..\/FileVector.h:11:29: error: 'Files' was not declared in this scope
I've tryied to include several directive in the header file..for example declaring the struct in the header and including vector header do the trick but this way i got loads of "multiple definitions/first defined here" error.
What can i do?
EDIT
Now my header looks like:
#ifndef FILEVECTOR_H_
#define FILEVECTOR_H_
#include <vector>
#include <windows.h>
struct Files{
HANDLE h;
WIN32_FIND_DATA info;
};
void FileVector(std::vector<Files> &,const char*,bool);
#endif /* FILEVECTOR_H_ */
At this point, i need to declare another prototype in another header:
void ProcessInput(vector<Files>&);
but i can't use the same trick as above cause i'll have to re-define the Files struct. How can i solve this?
Make sure to include <vector> in your header file. You also mention that the definition of Files is within the cpp file, you should move it to the header as well.
Also place proper header guards to avoid multiple definition errors:
#ifndef MY_HEADER_FILE_GUARD
#define MY_HEADER_FILE_GUARD
... your content here ...
#endif /*MY_HEADER_FILE_GUARD*/
Update:
Simply including filevector.h from your new header would do. However, it looks like Files should be defined in a header of its own and included from the two headers that make use of it.
When building my small C++ project, I get the following 2 errors, can't figure out the cause:
error: using typedef-name 'TTF_Font' after 'struct'.
Points to the following line of code: struct TTF_Font; in Foo.h.
error: 'TTF_Font' has a previous declaration here.
Points to the following line of code: typedef struct _TTF_Font TTF_Font; in SDL_ttf.h.
I've narrowed it down to the following files in a new test project:
Foo.h:
#ifndef FOO_H
#define FOO_H
struct TTF_Font;
class Foo
{
TTF_Font* font;
};
#endif // FOO_H
Foo.cpp:
#include "Foo.h"
#include "SDL/SDL_ttf.h"
// No implementation, just testing
Main.cpp:
#include "Foo.h"
int main(int argc, const char* argv[])
{
Foo a;
return 0;
}
Do you guys know what I'm doing wrong?
My goal is to forward declare TTF_Font, so I can use it in my header file without including the SDL_ttf header file. I read that including header files in other header files was kinda bad practice, so I switched to forward declarations. All my other forward declarations work fine except this single struct.
When I replace the forward declaration struct TTF_Font; with the header include #include "SDL/SDL.ttf.h", it compiles without errors. So I can use that, but I want to know WHY, dammit :-).
Extra info: I'm using the Code::Blocks IDE with mingw32 compiler. Project uses the SDL graphics library. Not much C++ experience yet, come from C# background.
You are trying to forward declare something as a different type to what it actually is.
You are declaring:
struct TTF_Font;
when the error message indicates that TTF_Font is actually a typedef, not a struct:
typedef struct _TTF_Font TTF_Font;
The stuct is actually called _TTF_Font.
You can declare the same typedef multiple times so you can just use the typedef declaration instead of the forward declaration to declare the struct and introduce the typedef although it does feel a bit like you are using implementation details of the header that you are trying to defer including.
The problem is that in this code snippet:
struct foo_t;
typedef struct foo { ... } foo_t;
The first line is a forward-declaration of a different struct, whose name clashes with the typedef. The forward declaration in this case needs to be struct foo;, because the name of the struct itself is foo.
I am new to this website and I am trying a simple inheritance example in C++.
I checked my code lots of times and I really see nothing wrong with it, however the compilers gives me errors:
my code:
#ifndef READWORDS_H
#define READWORDS_H
using namespace std;
#include "ReadWords.h"
/**
* ReadPunctWords inherits ReadWords, so MUST define the function filter.
* It chooses to override the default constructor.
*/
class ReadPunctWords: public ReadWords {
public:
bool filter(string word);
};
#endif
And the messages I get from the compiler:
ReadPunctWords.h:11: error: expected class-name before '{' token
ReadPunctWords.h:13: error: `string' has not been declared
ReadPunctWords.h:13: error: ISO C++ forbids declaration of `word' with no type
Tool completed with exit code 1
I am really not sure where I get it wrong as it looks just fine to me?
Thank you for any mistakes you might spot.
You need to include string:
#include <string>
That said, don't use using namespace! Especially at file-scope, and definitely not in a header file. Now any unit that includes this file is forced to succumb to everything in the std namespace.
Take that out, and qualify your names:
bool filter(std::string word);
It's arguable more readable, too. Additionally, you should take your string as a const&:
bool filter(const std::string& word);
To avoid having to copy the string unnecessarily. Lastly, your header guards seem off. Should they be changed? As of now, they seem like the same ones that would be used in your other header, which might effectively stop it from being included.
If you define READWORDS_H and then include ReadWords.h, and if that also has:
#ifndef READWORDS_H
#define READWORDS_H
Then nothing in that file will be processed. If that's the case, ReadWords as a class won't be defined, and you cannot inherit from it. Your guard should probably be:
READPUNCTWORDS_H
You need to include <string> and specify the namespace:
#include <string>
using namespace std;
Also, your include guard should probably be named READPUNCHTWORDS_H rather than READWORDS_H.
Edit: On second thought, GMan is right about not putting using namespace in a header file - qualify the string with std::string instead.
This particular form of error is often caused by a type not being defined (at least when the code looks syntactically correct), in this case probably the class ReadWords but maybe also std::string.
You need to include to get std::string, as other posters have written, but also your guard
#ifndef READWORDS_H
#define READWORDS_H
almost certainly conflicts with the guard in ReadWords.h. You need to make sure your guards are distinct in different header files otherwise you will get conflicts like this. You should change the guard to something like
#ifndef READPUNCTWORDS_H
#define READPUNCTWORDS_H
// ...
#endif
In fact, it's better to have even more verbose guards to make sure they don't conflict. We use guards of the form
#ifndef MODULE_OR_PATH_FILE_H_INCLUDED
#define MODULE_OR_PATH_FILE_H_INCLUDED
// ...
#endif
This ensures different modules or libraries with similarly named headers don't conflict, the INCLUDED thing at the end is my own particular foible that makes the guard slightly more readable.
It's also bad practice to place a "using" declaration in a header file, because it places (potentially unwanted or conflicting) symbols in the global namespace everywhere you include the header. Personally, I prefer to retain the namespace for clarity or alias it in cpp files if it's a long one, for example
namespace fs = boost::filesystem;
also looks like something wrong with ReadWords class def (message for line 11)- we need to see .h file
aha - the sentinial def you use prevents the readwords.h include being read
you need
#ifndef _READPUNCTWORDS_H
#define _READPUNCTWORDS_H
I also suspect the include guards. If they are named the same way in both header files, the result should be something like the following when ReadWords.h is pasted into ReadPunctWords.h.
#ifndef READWORDS_H // Is READWORDS_H defined? No, proceeding
#define READWORDS_H // Now it is defined
// Contents of ReadWords.h is pasted in here
#ifndef READWORDS_H // Is READWORDS_H defined? Yes, ignoring the contents of ReadWords.h (skipping til #endif)
#define READWORDS_H
class ReadWords { ... }; // This is never seen by the compiler as the preprocessor removed it
#endif
class ReadPunctWords: public ReadWords { // Error: ReadWords isn't declared...
public:
bool filter(string word);
};
#endif