argparse icon indicating copy to clipboard operation
argparse copied to clipboard

Windows.h defines min() as a macro, which conflicts with argparse

Open tuankiet65 opened this issue 4 years ago • 1 comments

This program fails to compile with MSVC 19.16.27045 and Windows SDK 10.0.19041.0:

#include <Windows.h>
#include <argparse/argparse.hpp>

int main(int argc, char *argv[])
{
    argparse::ArgumentParser program("test");

    program.add_argument("--verbose")
        .help("increase output verbosity")
        .default_value(false)
        .implicit_value(true);

    try
    {
        program.parse_args(argc, argv);
    }
    catch (const std::runtime_error &err)
    {
        std::cout << err.what() << std::endl;
        std::cout << program;
        exit(0);
    }

    if (program["--verbose"] == true)
    {
        std::cout << "Verbosity enabled" << std::endl;
    }
}

The error messages are super cryptic:

argparse.hpp(102): error C2589: '(': illegal token on right side of '::'
argparse.hpp(102): error C2065: 'size': undeclared identifier
argparse.hpp(102): error C2059: syntax error: '?'
argparse.hpp(102): error C2059: syntax error: ')'
argparse.hpp(103): error C2143: syntax error: missing ';' before '{' 
argparse.hpp(103): error C2065: 'out': undeclared identifier 
argparse.hpp(103): error C2065: 'v': undeclared identifier 
argparse.hpp(103): error C2059: syntax error: ')' 
argparse.hpp(104): error C2065: 'size': undeclared identifier 
argparse.hpp(105): error C2065: 'out': undeclared identifier 
argparse.hpp(107): error C2065: 'out': undeclared identifier 
argparse.hpp(109): error C2059: syntax error: 'if' 
argparse.hpp(111): error C2143: syntax error: missing ';' before '<<'
argparse.hpp(111): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 
argparse.hpp(112): error C2059: syntax error: 'return' 
argparse.hpp(113): error C2059: syntax error: '}' 
argparse.hpp(113): error C2143: syntax error: missing ';' before '}' 
argparse.hpp(113): error C2065: 'T': undeclared identifier 
argparse.hpp(113): error C2923: 'argparse::details::is_streamable_v': 'T' is not a valid template type argument for parameter 'T' 
argparse.hpp(115): error C2143: syntax error: missing ';' before '<<' 
argparse.hpp(115): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int 
argparse.hpp(115): error C2086: 'int argparse::details::out': redefinition 
argparse.hpp(116): error C2059: syntax error: 'return' 
argparse.hpp(117): error C2059: syntax error: '}' 
argparse.hpp(117): error C2143: syntax error: missing ';' before '}' 
argparse.hpp(119): error C2059: syntax error: '}' 
argparse.hpp(119): error C2143: syntax error: missing ';' before '}' 
argparse.hpp(120): error C2143: syntax error: missing ';' before '}' 
argparse.hpp(120): error C2059: syntax error: '}' 

After some digging, it turns out that Windows.h defines min as a macro:

#ifndef min
#define min(a,b)            (((a) < (b)) ? (a) : (b))
#endif

which conflicts with argparse's use of std::min in argparse.hpp:120, since min(...) will get expanded by the macro:

          std::next(val.begin(), std::min(size, repr_max_container_size) - 1),

This StackOverflow answer mentions wrapping std::min in parentheses to prevent macro-expanding:

          std::next(val.begin(), (std::min)(size, repr_max_container_size) - 1),

but if you're not willing to make an exception for this, I think the README should mention another solution, which involves defining NOMINMAX before including Windows.h to tell it not to define min():

#define NOMINMAX
#include <Windows.h>
#include <argparse/argparse.hpp>

tuankiet65 avatar Jun 18 '21 20:06 tuankiet65

#109 should fix it

Chuvi-w avatar Aug 05 '21 07:08 Chuvi-w

I'm having the same issue, even though I'm running the most recent version (v2.9) Compilation succeed only if NOMINMAX is defined Any suggestions?

Context:

  • Windows 10 Pro
  • Version 10.0.19045 Build 19045
  • MSBuild version 17.7.2+d6990bcfa (Visual Studio 2022)

carlocorradini avatar Oct 10 '23 14:10 carlocorradini