c++visual-c++mfcrapidjson

rapidjson works on console application but not on mfc application


I have tried to use rapidjson on a MFC application (VS2019). I simply included the rapidjson header as follow:

#include "rapidjson/document.h"

BOOL CMyProjectDoc::OnNewDocument()
{
    if (! CDocument::OnNewDocument())
        return FALSE;

    // TODO: add reinitialization code here
    // (SDI documents will reuse this document)

    const char* json = "{\"project\":\"rapidjson\",\"stars\":10}";
    rapidjson::Document d;
    d.Parse(json);

    return TRUE;
}

and I got:

\rapidjson\allocators.h(437,5): warning C4003: not enough arguments for function-like macro invocation 'max'
\rapidjson\allocators.h(437,5): error C2760: syntax error: unexpected token ')', expected 'expression'

I tried to use the same rapidjson in a console application, built with the same VS2019:

#include "rapidjson/document.h"

int main()
{
    const char* json = "{\"project\":\"rapidjson\",\"stars\":10}";
    rapidjson::Document d;
    d.Parse(json);
    return 0;
}

No errors. Of course, I compared the projects settings, even if they are the same:

enter image description here

the MFC projects throws errors ... why ?


Solution

  • The Windows headers, by default, define macros with names min and max, that can conflict with library code. To fix that you need to request that the Windows headers don't define the macros, by using a #define NOMINMAX proprocessor directive prior to including any Windows header files.

    To make sure this doesn't happen too late it's advisable to pass the proprocessor symbol on the command line. To do this from Visual Studio, right-click the project, select Properties, navigate to Configuration Properties -> C/C++ -> Preprocessor and add NOMINMAX to the Preprocessor Definitions. This needs to be done for all Configuration and Platform combinations.


    That covers the case when consuming a library. If, on the other hand, you are authoring a library you can actively prevent those collisions from happening: By wrapping min and max in parentheses, it suppresses preprocessor expansion. The following will compile regardless of whether NOMINMAX is defined:

    #include <Windows.h>
    #include <algorithm>
    
    int main() {
        auto m = (std::min)(42, 7);
        return m;
    }