I'm working on a framework that is used within managed code, but relies on the native 3rd party library
cereal[
^]. I might have a problem with cereal's use of static variables: their instantiation causes Visual Studio to issue the
warning C4835[
^]. It's a level 1 warning, so I''m not taking it lightly, and although the program compiles and runs, I have a suspicion there is something not quite right.
I've found
this suggestion[
^] which should tell the compiler to compile this code as native, but although cereal is header only, this tip doesn't work for the code that actually invokes cereal using the macro
CEREAL_CLASS_VERSION(,)
.
I've only started working with managed code, and duckduckgo-ing for a solution got me this far (see links above). googl-ing didn't get me any further. Does anyone here have an idea how to properly resolve this without modifying the cereal headers, and without disabling the warning? Otherwise, can anyone familiar with ceral tell me whether or not the warning can be safely ignored? As far as I can tell I shouldn't, but I may be wrong.
What I have tried:
#pragma managed(push, off)
#include "cereal.hpp" // normally produces C4835, but not with the help of this pragma
class foo { int x; };
CEREAL_CLASS_VERSION(foo, 0); #pragma managed(pop)
I've managed to pinpoint the locations (2 positions) within Cereal that are causing the issue. By adding the abovementioned #pragma statements in these locations, I could reliably eliminate the warning. See below:
namespace cereal
{
namespace detail
{
template <class T>
class CEREAL_DLL_EXPORT StaticObject
{
private:
static T & create()
{
#pragma warning(push)
#pragma warning(disable : 4835)
static T t;
#pragma warning(pop)
(void)instance;
return t;
}
StaticObject( StaticObject const & ) {}
public:
static T & getInstance()
{
return create();
}
class LockGuard
{
#if CEREAL_THREAD_SAFE
public:
LockGuard(std::mutex & m) : lock(m) {}
private:
std::unique_lock<std::mutex> lock;
#else
public:
LockGuard(LockGuard const &) = default; ~LockGuard() CEREAL_NOEXCEPT {} #endif
};
static LockGuard lock()
{
#if CEREAL_THREAD_SAFE
static std::mutex instanceMutex;
return LockGuard{instanceMutex};
#else
return LockGuard{};
#endif
}
private:
static T & instance;
};
#pragma warning(push)
#pragma warning(disable : 4835)
template <class T> T & StaticObject<T>::instance = StaticObject<T>::create();
#pragma warning (pop)
} }
The question remains whether it's actually safe to ignore this warning, or if there is a reasonable way to properly fix it other than modifying 3rd party code!