I have a class that is exported and it uses a header only structure as a member variable.
#include "SomeStruct.h"
class API_CLASS SomeClass
{
public:
// ...
private:
#pragma warning( push )
#pragma warning( disable: 4251 )
SomeStruct _active;
#pragma warning( pop )
};
I get warning 4251 as the structure is not exported. The structure is part of an external code and not a part of current scope.
I would like to make this code a bit more readable as this is a header I will distribute.
Ideally, I want the class to read
#include "SomeStruct.h"
class API_CLASS SomeClass
{
public:
// ...
private:
DISABLE_WARNING_BEGIN(4251)
SomeStruct _active;
DISABLE_WARNING_END
};
It may be more work to disable multiple warnings but if that can be done, then great but not necessary. The macro should result in code only for WIN32 environment. I have tried to write the macro but to include a '#' is beyond me.
I can live with this. This is better than what I have now.
#include "SomeStruct.h"
class API_CLASS SomeClass
{
public:
// ...
private:
#pragma warning(suppress: 4251)
SomeStruct _active;
};
Thanks to Heinirichj
To add #pragma into a MACRO, you may use:
__pragma with MSVC
_Pragma with gcc
See Pragma in define macro for more detail.
Related
I know that many questions have been asked with the similar title. I have a class like this:
in CustomAllocator.h
namespace MemoryMgmt
{
class MemoryManager
{
.....
}
}
class CustomAllocator
{
public:
void * operator new(size_t i_size);
void operator delete(void*, void*);
virtual ~CustomAllocator(){};
#pragma warning(suppress: 4251)
static boost::thread_specific_ptr< MemoryMgmt::MemoryManager> memory_manager_currentHA;
};
// boost::thread_specific_ptr< MemoryMgmt::MemoryManager > CustomAllocator::memory_manager_currentHA;
inline void * CustomAllocator::operator new(size_t i_size)
{
if (!g_memory_manager_currentHA.get()) {
memory_manager_currentHA.reset(new MemoryMgmt::MemoryManager);
}
return memory_manager_currentHA->AllocateChars(i_size);
}
inline void CustomAllocator::operator delete(void * , void*)
{
//Should not be used
ASSERT(!"Placement delete should not be used for memory objects");
}
in CustomAllocator.cpp
#include <CustomAllocator.h>
MemoryMgmt::MemoryManager CustomAllocator::memory_manager_current = MemoryMgmt::MemoryManager();
boost::thread_specific_ptr< MemoryMgmt::MemoryManager > CustomAllocator::memory_manager_currentHA;
The header file calls in many different files. Of course there is a linking problem due to the declaration of the memory_manager_currentHA in the header file. However, when I declare it in cpp file there would be an other error:
error C2220: warning treated as error - no 'object' file generated
I know that this error is due to the warning level that has been set for the (Level3 /W3) in visual studio C/C++ general configuration page.
I am wondering if there would be any solution to resolve this issue without changing the warning level.
EDIT:
For example one of the usage of the header file:
#include "CustomAllocator.h"
class MVeryLongData : public CustomAllocator
{
....
}
I finally resolved the issue by disabling locally the warnings.
#pragma warning (push)
#pragma warning(disable: 4100)
#include <boost/thread.hpp>
#pragma warning(pop)
#pragma warning (push)
#pragma warning(disable: 4251)
static boost::thread_specific_ptr< MemoryMgmt::MemoryManager> memory_manager_currentHA;
#pragma warning(pop)
You should move the definition (storage) of memory_manager_currentHA to the .cpp file.
I have one question about using pragma in c++ classes.
I've read there (Use of #pragma pack on a class) that use pragma around c++ class is not recommended, but can I use pragma like this:
class TestClass {
public:
ConfigProtocol();
#pragma pack(1)
struct t_config_header {
quint8 version;
quint8 da;
quint16 sa;
quint16 counter;
};
#pragma pack()
};
will not it be mistake?
Short answer: Yes you can (and in your case, as it seems you are implementing a communcation protocol, in fact, should) do it.
The way you are using the pragma is only affecting the structure which invalidates the arguments made in the StackOverflow answer you are linking to: The struct is not significantly changing as long as it stays a struct.
I was trying to create a small define to work around this bug in QITABENT and I noticed peculiar behavior of the #pragma warning (disable: ...) statement.
In the following code the define QITABENT generates warning C4838
static const QITAB qit[] =
{
QITABENT(MediaPlayerCallback, IMFPMediaPlayerCallback)
};
I can easily suppress this warning, this works:
#pragma warning( push )
#pragma warning( disable: 4838 )
static const QITAB qit[] =
{
QITABENT(MediaPlayerCallback, IMFPMediaPlayerCallback)
//{ 0 },
};
return QISearch(this, qit, riid, ppv);
#pragma warning( pop )
Now I wanted to make a define QITABENTEX which automatically suppresses the warning generated by QITABENT. But it seems impossible because when I write the following code the warning C4838 is not suppressed.
static const QITAB qit[] =
{
#pragma warning( push )
#pragma warning( disable: 4838 )
QITABENT(MediaPlayerCallback, IMFPMediaPlayerCallback)
#pragma warning( pop )
//{ 0 },
};
How does the compiler interpret this code in such a way that the warning is not suppressed?
This probably has to with when the definition for QITABENT is fully resolved.
(Note that I'm not really interested in making the above code work, I'm just really curious how its interpreted by the compiler)
Addendum:
Regarding the close vote and clarification: I got into a discussion with someone giving a shotgun/link-only answer, presumably only reading the question halfway through (since the question explained how to use #pragma in a macro which is not what I'm asking) now that answer got (self) deleted and I got a close vote for being unclear. So let me reiterate my intentions with this question:
This question is not about finding a define to suppress this warning
This question is not about how to suppress a warning in VC++ in general
This question is about trying to understand what happens with the three lines of suppression code in the last code sample. Why do they not have effect in that exact position (in an array initialization) but do have effect outside the array initialization? This probably boils down to answering how and when the pragma statements and macross are resolved.
The initializer list terminates with the closing curly bracket }, and that is where warning is generated.
Try this:
static const QITAB qit[] =
{
QITABENT(Derived, Base)
#pragma warning( push )
#pragma warning( disable: 4365 )
}
#pragma warning( pop )
;
[edited]
Per Mr.C64's comment below, corrected the order of parameters in QITABENT(Derived, Base).
I have a code structure like this
myobj.h
#pragma once
struct myobj {
myobj();
...
} Myobj;
myobj.cpp
#include "myobj.h"
myobj::myobj() { ... }
...
mysketch.ino
#include "myobj.h"
Myobj.someMethod();
...
I understand this won't work because Arduino IDE compiles each file separatedly, so #pragma once won't help me to avoid the multiple definition error (Myobj was created twice) in the linking phase.
I'd like not to bother the user of my future library to create the global object by himself (the object will be used as singleton anyway). The working idea was to use macro:
myobj.h
#pragma once
struct myobj {
myobj();
...
};
#ifndef _MYOBJ_
myobj Myobj;
#endif
myobj.cpp
#define _MYOBJ_
#include "myobj.h"
myobj::myobj() { ... }
...
But then I have to remember to define this macro everywhere but in the ino file. It would be nice to detect that the myobj.h is included in the .ino file with setup and loop function. Is such detection possible without adding any extra code in that ino file? Is there any other way to define global object in library?
When I look into other libraries (like Servo), global object is created in the ino example. I can live with that, but there are objects like Serial that is auto-created somehow, I wonder how.
Ah, I found the solution in the SD library: one clever extern keyword!
myobj.h
#pragma once
struct myobj {
myobj();
...
};
extern myobj Myobj;
myobj.cpp
#include "myobj.h"
myobj::myobj() { ... }
...
myobj Myobj;
mysketch.ino
#include "myobj.h"
Myobj.someMethod(); // works, no multiple definition error
...
One of the header files is as follows -
#include "stdafx.h"
class AAA
{
public:
std::string strX;
std::string strY;
};
When I try to compile the project, I get the error
error C2011: 'AAA' : 'class' type redefinition
Nowhere else in my program have I redefined the class AAA. How do I fix this?
Change to code to something like this:
#ifndef AAA_HEADER
#define AAA_HEADER
#include "stdafx.h"
class AAA
{
public:
std::string strX;
std::string strY;
};
#endif
If you include this header file more than once in some source file, include guards will force compiler to generate class only once so it will not give class redefinition error.
Adding
#pragma once
to the top of your AAA.h file should take care of the problem.
like this
#include "stdafx.h"
#pragma once
class AAA
{
public:
std::string strX;
std::string strY;
};
In addition to the suggested include guards you need to move #include "stdafx.h" out of the header. Put it at the top of the cpp file.
I met this problem today in VS 2017. I added #pragma once, but it didn't work until I added a macro definition:
// does not work
#pragma once
// works with or without #pragma once
#ifndef _HEADER_AAA
#define _HEADER_AAA
//
// my code here....
//
#endif
I have no clue how to explain this, but it is a solution for me.
There are two ways to go about this but you can't use both. Make sure to wrap the class definition with a compiler directive that the class declaration only gets compiled once:
#include "stdafx.h"
#pragma once
class AAA{
public:
std::string strX;
std::string strY;
};
-or-
#include "stdafx.h"
#ifndef AAA_HEADER_
#define AAA_HEADER_
class AAA
{
public:
std::string strX;
std::string strY;
};
#endif
Also: note the class import statement should be at the top of your file.