I'm working on a C++ to C# wrapper using C++/CLR and MS VS Community 2015 (Version 14.0.25431.01 Update 3).
Compiling the single header json.hpp fails with described error in the title. The json.hpp version in 3.1.1.
I uploaded a tiny test project to reproduce the compile error:
TestLibrary.zip
For me a possible workaround is to encapsulate the json object and return the dump()ed string to pass to the C++/CLR and pass that string to the C# world instead of passing the dump()ed string from my C++/CLR class to the C# environment.
Thanks in advance.
Can you compile and run the unit tests (https://github.com/nlohmann/json#execute-unit-tests)?
I'll give that a try. I should note that compiling json.hpp in a native C++ project in the same Visual Studio is successful.
First of all, i forgot to disable using precompiled headers. With the provided TestLibrary.zip you was not able compiling to reproduce the error. Here is the corrected one:
TestLibrary.zip
The error output of that project:
1>------ Rebuild All started: Project: TestLibrary, Configuration: Debug x64 ------
1> AssemblyInfo.cpp
1> TestLibrary.cpp
1>c:\prg\test\testlibrary\testlibrary\json.hpp(1808): error C2664: 'std::shared_ptr<nlohmann::detail::input_buffer_adapter> std::make_shared<nlohmann::detail::input_buffer_adapter,nullptr,const size_t&>(nullptr &&,const size_t &)': cannot convert argument 1 from 'nullptr' to 'nullptr &&'
1> c:\prg\test\testlibrary\testlibrary\json.hpp(1808): note: nullptr can only be converted to pointer or handle types
1> c:\prg\test\testlibrary\testlibrary\json.hpp(15582): note: see reference to function template instantiation 'nlohmann::detail::input_adapter::input_adapter<IteratorType,0>(IteratorType,IteratorType)' being compiled
1> with
1> [
1> IteratorType=const char *
1> ]
1> c:\prg\test\testlibrary\testlibrary\json.hpp(17144): note: see reference to function template instantiation 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer> nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::parse<const char*,0>(IteratorType,IteratorType,const std::function<bool (int,nlohmann::detail::parser<nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>::parse_event_t,BasicJsonType &)>,const bool)' being compiled
1> with
1> [
1> IteratorType=const char *,
1> BasicJsonType=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>
1> ]
1> c:\prg\test\testlibrary\testlibrary\json.hpp(17144): note: see reference to function template instantiation 'nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer> nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>::parse<const char*,0>(IteratorType,IteratorType,const std::function<bool (int,nlohmann::detail::parser<nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>>::parse_event_t,BasicJsonType &)>,const bool)' being compiled
1> with
1> [
1> IteratorType=const char *,
1> BasicJsonType=nlohmann::basic_json<std::map,std::vector,std::string,bool,int64_t,uint64_t,double,std::allocator,nlohmann::adl_serializer>
1> ]
1> Generating Code...
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
Here is the result of the unit test:
C:\prg\Test\json\build>ctest --output-on-failure -C Debug
Test project C:/prg/Test/json/build
Start 1: test-algorithms_default
1/76 Test #1: test-algorithms_default ............. Passed 0.10 sec
Start 2: test-algorithms_all
2/76 Test #2: test-algorithms_all ................. Passed 0.02 sec
Start 3: test-allocator_default
3/76 Test #3: test-allocator_default .............. Passed 0.03 sec
Start 4: test-allocator_all
4/76 Test #4: test-allocator_all .................. Passed 0.01 sec
Start 5: test-capacity_default
5/76 Test #5: test-capacity_default ............... Passed 0.05 sec
Start 6: test-capacity_all
6/76 Test #6: test-capacity_all ................... Passed 0.03 sec
Start 7: test-cbor_default
7/76 Test #7: test-cbor_default ................... Passed 17.71 sec
Start 8: test-cbor_all
8/76 Test #8: test-cbor_all ....................... Passed 164.93 sec
Start 9: test-class_const_iterator_default
9/76 Test #9: test-class_const_iterator_default ... Passed 0.05 sec
Start 10: test-class_const_iterator_all
10/76 Test #10: test-class_const_iterator_all ....... Passed 0.02 sec
Start 11: test-class_iterator_default
11/76 Test #11: test-class_iterator_default ......... Passed 0.04 sec
Start 12: test-class_iterator_all
12/76 Test #12: test-class_iterator_all ............. Passed 0.03 sec
Start 13: test-class_lexer_default
13/76 Test #13: test-class_lexer_default ............ Passed 0.04 sec
Start 14: test-class_lexer_all
14/76 Test #14: test-class_lexer_all ................ Passed 0.02 sec
Start 15: test-class_parser_default
15/76 Test #15: test-class_parser_default ........... Passed 0.24 sec
Start 16: test-class_parser_all
16/76 Test #16: test-class_parser_all ............... Passed 0.22 sec
Start 17: test-comparison_default
17/76 Test #17: test-comparison_default ............. Passed 0.15 sec
Start 18: test-comparison_all
18/76 Test #18: test-comparison_all ................. Passed 0.14 sec
Start 19: test-concepts_default
19/76 Test #19: test-concepts_default ...............***Failed 0.04 sec
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test-concepts.exe is a Catch v1.9.7 host application.
Run with -? for options
-------------------------------------------------------------------------------
concepts
class iterator
CopyConstructible
-------------------------------------------------------------------------------
C:\prg\Test\json\test\src\unit-concepts.cpp(129)
...............................................................................
C:\prg\Test\json\test\src\unit-concepts.cpp(132): FAILED:
CHECK( std::is_nothrow_copy_constructible<json::const_iterator>::value )
with expansion:
false
===============================================================================
test cases: 1 | 0 passed | 1 failed
assertions: 31 | 30 passed | 1 failed
Start 20: test-concepts_all
20/76 Test #20: test-concepts_all ...................***Failed 0.02 sec
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test-concepts.exe is a Catch v1.9.7 host application.
Run with -? for options
-------------------------------------------------------------------------------
concepts
class iterator
CopyConstructible
-------------------------------------------------------------------------------
C:\prg\Test\json\test\src\unit-concepts.cpp(129)
...............................................................................
C:\prg\Test\json\test\src\unit-concepts.cpp(132): FAILED:
CHECK( std::is_nothrow_copy_constructible<json::const_iterator>::value )
with expansion:
false
===============================================================================
test cases: 1 | 0 passed | 1 failed
assertions: 31 | 30 passed | 1 failed
Start 21: test-constructor1_default
21/76 Test #21: test-constructor1_default ........... Passed 0.16 sec
Start 22: test-constructor1_all
22/76 Test #22: test-constructor1_all ............... Passed 0.13 sec
Start 23: test-constructor2_default
23/76 Test #23: test-constructor2_default ........... Passed 0.03 sec
Start 24: test-constructor2_all
24/76 Test #24: test-constructor2_all ............... Passed 0.02 sec
Start 25: test-convenience_default
25/76 Test #25: test-convenience_default ............ Passed 0.03 sec
Start 26: test-convenience_all
26/76 Test #26: test-convenience_all ................ Passed 0.01 sec
Start 27: test-conversions_default
27/76 Test #27: test-conversions_default ............ Passed 0.15 sec
Start 28: test-conversions_all
28/76 Test #28: test-conversions_all ................ Passed 0.14 sec
Start 29: test-deserialization_default
29/76 Test #29: test-deserialization_default ........ Passed 0.07 sec
Start 30: test-deserialization_all
30/76 Test #30: test-deserialization_all ............ Passed 0.06 sec
Start 31: test-element_access1_default
31/76 Test #31: test-element_access1_default ........ Passed 0.09 sec
Start 32: test-element_access1_all
32/76 Test #32: test-element_access1_all ............ Passed 0.06 sec
Start 33: test-element_access2_default
33/76 Test #33: test-element_access2_default ........ Passed 0.12 sec
Start 34: test-element_access2_all
34/76 Test #34: test-element_access2_all ............ Passed 0.07 sec
Start 35: test-inspection_default
35/76 Test #35: test-inspection_default ............. Passed 30.10 sec
Start 36: test-inspection_all
36/76 Test #36: test-inspection_all ................. Passed 30.68 sec
Start 37: test-items_default
37/76 Test #37: test-items_default .................. Passed 0.08 sec
Start 38: test-items_all
38/76 Test #38: test-items_all ...................... Passed 0.04 sec
Start 39: test-iterators1_default
39/76 Test #39: test-iterators1_default ............. Passed 0.18 sec
Start 40: test-iterators1_all
40/76 Test #40: test-iterators1_all ................. Passed 0.11 sec
Start 41: test-iterators2_default
41/76 Test #41: test-iterators2_default ............. Passed 0.12 sec
Start 42: test-iterators2_all
42/76 Test #42: test-iterators2_all ................. Passed 0.10 sec
Start 43: test-json_patch_default
43/76 Test #43: test-json_patch_default ............. Passed 0.13 sec
Start 44: test-json_patch_all
44/76 Test #44: test-json_patch_all ................. Passed 0.11 sec
Start 45: test-json_pointer_default
45/76 Test #45: test-json_pointer_default ........... Passed 0.05 sec
Start 46: test-json_pointer_all
46/76 Test #46: test-json_pointer_all ............... Passed 0.02 sec
Start 47: test-merge_patch_default
47/76 Test #47: test-merge_patch_default ............ Passed 0.05 sec
Start 48: test-merge_patch_all
48/76 Test #48: test-merge_patch_all ................ Passed 0.02 sec
Start 49: test-meta_default
49/76 Test #49: test-meta_default ................... Passed 0.03 sec
Start 50: test-meta_all
50/76 Test #50: test-meta_all ....................... Passed 0.01 sec
Start 51: test-modifiers_default
51/76 Test #51: test-modifiers_default .............. Passed 0.08 sec
Start 52: test-modifiers_all
52/76 Test #52: test-modifiers_all .................. Passed 0.05 sec
Start 53: test-msgpack_default
53/76 Test #53: test-msgpack_default ................ Passed 17.54 sec
Start 54: test-msgpack_all
54/76 Test #54: test-msgpack_all .................... Passed 157.68 sec
Start 55: test-noexcept_default
55/76 Test #55: test-noexcept_default ............... Passed 0.03 sec
Start 56: test-noexcept_all
56/76 Test #56: test-noexcept_all ................... Passed 0.01 sec
Start 57: test-pointer_access_default
57/76 Test #57: test-pointer_access_default ......... Passed 0.03 sec
Start 58: test-pointer_access_all
58/76 Test #58: test-pointer_access_all ............. Passed 0.02 sec
Start 59: test-readme_default
59/76 Test #59: test-readme_default ................. Passed 0.03 sec
Start 60: test-readme_all
60/76 Test #60: test-readme_all ..................... Passed 0.02 sec
Start 61: test-reference_access_default
61/76 Test #61: test-reference_access_default ....... Passed 0.04 sec
Start 62: test-reference_access_all
62/76 Test #62: test-reference_access_all ........... Passed 0.02 sec
Start 63: test-regression_default
63/76 Test #63: test-regression_default ............. Passed 30.19 sec
Start 64: test-regression_all
64/76 Test #64: test-regression_all ................. Passed 29.04 sec
Start 65: test-serialization_default
65/76 Test #65: test-serialization_default .......... Passed 0.04 sec
Start 66: test-serialization_all
66/76 Test #66: test-serialization_all .............. Passed 0.01 sec
Start 67: test-testsuites_default
67/76 Test #67: test-testsuites_default ............. Passed 0.34 sec
Start 68: test-testsuites_all
68/76 Test #68: test-testsuites_all ................. Passed 0.36 sec
Start 69: test-to_chars_default
69/76 Test #69: test-to_chars_default ............... Passed 0.05 sec
Start 70: test-to_chars_all
70/76 Test #70: test-to_chars_all ................... Passed 0.03 sec
Start 71: test-ubjson_default
71/76 Test #71: test-ubjson_default ................. Passed 8.30 sec
Start 72: test-ubjson_all
72/76 Test #72: test-ubjson_all ..................... Passed 66.80 sec
Start 73: test-udt_default
73/76 Test #73: test-udt_default .................... Passed 0.04 sec
Start 74: test-udt_all
74/76 Test #74: test-udt_all ........................ Passed 0.02 sec
Start 75: test-unicode_default
75/76 Test #75: test-unicode_default ................ Passed 0.06 sec
Start 76: test-unicode_all
76/76 Test #76: test-unicode_all ....................***Timeout 1500.00 sec
100000 of 8860608 UTF-8 strings checked
200000 of 8860608 UTF-8 strings checked
300000 of 8860608 UTF-8 strings checked
400000 of 8860608 UTF-8 strings checked
500000 of 8860608 UTF-8 strings checked
600000 of 8860608 UTF-8 strings checked
700000 of 8860608 UTF-8 strings checked
800000 of 8860608 UTF-8 strings checked
900000 of 8860608 UTF-8 strings checked
1000000 of 8860608 UTF-8 strings checked
1100000 of 8860608 UTF-8 strings checked
1200000 of 8860608 UTF-8 strings checked
1300000 of 8860608 UTF-8 strings checked
1400000 of 8860608 UTF-8 strings checked
1500000 of 8860608 UTF-8 strings checked
1600000 of 8860608 UTF-8 strings checked
1700000 of 8860608 UTF-8 strings checked
1800000 of 8860608 UTF-8 strings checked
1900000 of 8860608 UTF-8 strings checked
2000000 of 8860608 UTF-8 strings checked
2100000 of 8860608 UTF-8 strings checked
2200000 of 8860608 UTF-8 strings checked
2300000 of 8860608 UTF-8 strings checked
2400000 of 8860608 UTF-8 strings checked
2500000 of 8860608 UTF-8 strings checked
2600000 of 8860608 UTF-8 strings checked
2700000 of 8860608 UTF-8 strings checked
2800000 of 8860608 UTF-8 strings checked
2900000 of 8860608 UTF-8 strings checked
3000000 of 8860608 UTF-8 strings checked
3100000 of 8860608 UTF-8 strings checked
3200000 of 8860608 UTF-8 strings checked
3300000 of 8860608 UTF-8 strings checked
3400000 of 8860608 UTF-8 strings checked
3500000 of 8860608 UTF-8 strings checked
3600000 of 8860608 UTF-8 strings checked
3700000 of 8860608 UTF-8 strings checked
3800000 of 8860608 UTF-8 strings checked
3900000 of 8860608 UTF-8 strings checked
4000000 of 8860608 UTF-8 strings checked
4100000 of 8860608 UTF-8 strings checked
4200000 of 8860608 UTF-8 strings checked
4300000 of 8860608 UTF-8 strings checked
4400000 of 8860608 UTF-8 strings checked
4500000 of 8860608 UTF-8 strings checked
4600000 of 8860608 UTF-8 strings checked
4700000 of 8860608 UTF-8 strings checked
4800000 of 8860608 UTF-8 strings checked
4900000 of 8860608 UTF-8 strings checked
5000000 of 8860608 UTF-8 strings checked
5100000 of 8860608 UTF-8 strings checked
5200000 of 8860608 UTF-8 strings checked
5300000 of 8860608 UTF-8 strings checked
5400000 of 8860608 UTF-8 strings checked
5500000 of 8860608 UTF-8 strings checked
5600000 of 8860608 UTF-8 strings checked
5700000 of 8860608 UTF-8 strings checked
5800000 of 8860608 UTF-8 strings checked
5900000 of 8860608 UTF-8 strings checked
6000000 of 8860608 UTF-8 strings checked
6100000 of 8860608 UTF-8 strings checked
6200000 of 8860608 UTF-8 strings checked
6300000 of 8860608 UTF-8 strings checked
6400000 of 8860608 UTF-8 strings checked
6500000 of 8860608 UTF-8 strings checked
6600000 of 8860608 UTF-8 strings checked
6700000 of 8860608 UTF-8 strings checked
6800000 of 8860608 UTF-8 strings checked
6900000 of 8860608 UTF-8 strings checked
7000000 of 8860608 UTF-8 strings checked
7100000 of 8860608 UTF-8 strings checked
96% tests passed, 3 tests failed out of 76
Label Time Summary:
all = 1951.09 sec*proc (38 tests)
default = 106.59 sec*proc (38 tests)
Total Test time (real) = 2064.65 sec
The following tests FAILED:
19 - test-concepts_default (Failed)
20 - test-concepts_all (Failed)
76 - test-unicode_all (Timeout)
Errors while running CTest
new information:
editing line 1808 from
ia = std::make_shared<input_buffer_adapter>(nullptr, len);
to
ia = std::make_shared<input_buffer_adapter>(__nullptr, len);
fixes the problem.
to check, if compiler is a C++/CLI compiler the predefined macro __cplusplus_cli is set.
my workaround so far is to add following lines somewhere at the beginning of json.hpp:
#if defined(__cplusplus_cli)
#define JSON_NULLPTR __nullptr
#else
#define JSON_NULLPTR nullptr
#endif
and change the mentioned line to:
ia = std::make_shared<input_buffer_adapter>(JSON_NULLPTR, len);
for further information:
https://stackoverflow.com/questions/7978006/nullptr-vs-nullptr
Thanks for the feedback! I wonder whether it is sufficient to make the change only at that position.
I think it should, because the keyword nullptr was introduced in C++/CLI for the managed side way before C++11. Now, with both side (C++/CLI and C++11) having the keyword nullptr, the language has to differentiate between unmanaged nullptr and managed nullptr. The new unmanaged nullptr became __nullptr.
The plain C++ code on Windows is working with my workaround, on my Embedded Linux environment with GCC/G++ also. Now I'm implementing the C# wrapper, then I'll see if that is working as well.
__nullptr
Uh, doesn't that mean that C++/CLI is not following C++ standards then? It should be using the C++ names for everything, else how would they expect to be able to compile C++ code?
Better yet, why didn't they put their weird .NET nullptr in a namespace, because it DEFINITELY should not be a keyword as the C++ spec reserves all keywords...
I think exactly the same. Here is Microsoft's statement:
https://msdn.microsoft.com/en-us/library/jj651642.aspx
or here:
https://msdn.microsoft.com/en-us/library/4ex65770.aspx
Also, why try to change nullptr in projects all around the world to fit it, why not instead just #define nullptr __nullptr then include the source files in a wrapper file?
Some wrapper cpp:
#define nullptr __nullptr
#include "../path/out/of/source/json.cpp"
#undef nullptr
And similar for headers too. This requires no changes to whatever number of libraries one may wish to use in the broken C++/CLR.
I'm surprised the compiler itself doesn't have a method to do that itself to regain some sense of standards?
That should work. I will try that out tomorrow at work. But yes, Microsoft's compiler should be smart enough to fit the keyword nullptr into C++ or into C++/CLI, because the compiler complains about using the "wrong" nullptr.
because the compiler complains about using the "wrong" nullptr.
You'd think that alone would show that the compiler could test both versions and use whichever is appropriate. ;-)
But eh, extend, embrace, then break compat, that's their way...
If the snippet from https://github.com/nlohmann/json/issues/987#issuecomment-369331492 fixes the the problem, I would close this issue.
But eh, extend, embrace, then break compat, that's their way...
Unfortunately, this is true.
Also do note, if a library has many cpp files that you want to fixup like that, you can actually import them all into a single file just fine (and in fact this usually speeds up compilation compared to multiple files too). :-)
Well, C++/CLI is technically a different language, and it had nullptr as a keyword way back in 2003, before C++ did. However, MS proposed it for C++ and said:
https://blogs.msdn.microsoft.com/hsutter/2003/11/23/ccli-keywords-under-the-hood/
nullptr: This has been proposed in WG21/J16 for C++0x, and at the
last meeting three weeks ago the evolution working group (EWG) was favorable to it
but wanted a few changes. The proposal
paper was written by me and Bjarne, and we will revise the paper for the
next meeting to reflect the EWG direction. If C++0x does adopt the proposal and chooses
to take the keyword nullptr then the list of C++/CLI reserved words
goes down to two and C++/CLI would just directly follow the C++0x design for nullptr,
including any changes C++0x makes to it.
Herb Sutter is a ISO C++ committee member for many many years. Furthermore as Microsoft's software architect he should have recognized, that introducing the keyword nullptr to C++11 will result in a clash with C++/CLI he worked at as well.
This was his post. He expected C++/CLI to follow C++0x. Not sure what happened there.
I don't know either. The idea to have both side in a class (i call that a Janus class) is fascinating. But knowing that C++/CLI does not fulfill the C++ standard bothers me.
If C++0x does adopt the proposal and chooses
to take the keyword nullptr then the list of C++/CLI reserved words
goes down to two and C++/CLI would just directly follow the C++0x design for nullptr,
including any changes C++0x makes to it.
Hmm, so when are they going to get around to that?
I think that will never happen, because you should not break broken compatibilities.
because you should not break broken compatibilities.
I would say that is the credo of Microsoft, except the past few major versions of Windows they've majorly broken some backwards compat... ^.^;
Ok, i tested @OvermindDL1 proposal macroizing the keyword nullptr:
#define nullptr __nullptr #include "../path/out/of/source/json.cpp" #undef nullptr
To make that work, you have to allow macroizing keywords by setting _ALLOW_KEYWORD_MACROS in your project file or somewhere in your src file. Otherwise the compiler spits:
fatal error C1189: #error: The C++ Standard Library forbids macroizing keywords. Enable warning C4005 to find the forbidden macro.
(Sorry Microsoft, that is a hack to teach to your compiler that nullptr IS an integral part of the C++ standard; what a stupid warning.)
Finally, that "hack" works indeed, but is really a PITA.