This is basically the same question as [SO]: C2491: \'std::numpunct<_Elem>::id\' : definition of dllimport static data member not allowed [closed], but considering the follow
The problem occurs because in the templated class std::numpunct
, the public variable id
is declared with _CRTIMP2_PURE_IMPORT
. I haven't chased down the definition of this, but it presumably sets this variable to be imported from the C runtime dll.
The way to fix the problem is to specialize the std::numpunct
class for the character type you wish to use, but declare the id
variable without _CRTIMP2_PURE_IMPORT
.
As the OP refers to a now out of date version of Visual Studio, I won't try and reference specific files or line numbers, as they may change from version to version. I also won't provide a specific specialization that can be used, as this probably depends upon exactly what the OP wants (it may be easy if they wish to just use their locale, or a bit more difficult if they wish to use other/any locale).
Start notes:
Approaches:
Quick (shallow) investigation
On VStudio IDE double click, on the 2nd note in the Output window (after attempting to compile the file), and from there repeated RClicks on relevant macros, and from the context menu choosing Go To Definition (F12):
xlocnum (#120): (comment is part of the original file/line)
__PURE_APPDOMAIN_GLOBAL _CRTIMP2_PURE static locale::id id; // unique facet id
yvals.h: (#494):
#define _CRTIMP2_PURE _CRTIMP2
crtdefs.h (#29+):
#ifndef _CRTIMP2
#if defined CRTDLL2 && defined _CRTBLD
#define _CRTIMP2 __declspec(dllexport)
#else
#if defined _DLL && !defined _STATIC_CPPLIB
#define _CRTIMP2 __declspec(dllimport) // @TODO - cfati: line #34: Here is the definition
#else
#define _CRTIMP2
#endif
#endif
#endif
As seen, __declspec(dllimport)
is defined on line #34. Repeating the process on the _DLL
macro, yielded no result. Found on [MSDN]: Predefined Macros:
_DLL Defined as 1 when the /MD or /MDd (Multithreaded DLL) compiler option is set. Otherwise, undefined.
I thought of 2 possible ways to go on (both resulting in a successful build):
#undef _DLL
(in main.cpp, before any #include
). This is a lame workaround (gainarie). It builds fine, but tampering with these things could (and most likely will) trigger Undefined Behavior at runtimeNone of these 2 options was fully satisfactory, so:
Going a (little) bit deeper
Tried to simplify things even more (main.cpp):
#include <sstream>
//typedef unsigned short CharType; // wchar_t unsigned short
#define CharType unsigned short
int main() {
std::basic_stringstream<CharType> stream;
CharType c = 0x41;
stream << c;
return 0;
}
Notes:
typedef
by #define
(to strip out new type definition complexity)unsigned short
which is wchar_t
's definition (/Zc:wchar_t-
) to avoid any possible type size / alignment differences
"Compiled" the above code with [MSDN]: /E (Preprocess to stdout) and [MSDN]: /EP (Preprocess to stdout Without #line Directives) (so that the warnings/errors only reference line numbers from current file):
#define
(wchar_t
vs. unsigned short
) somewhere at the very endwchar_t
one compiled while the unsigned short
failed with the same error#pragma message
statements (yes, they are handled by the preprocessor, but still) in the file that fails (before each warning/note), noticed some difference between the 2 #define
s, but so far unable to figure out why 1template<> struct char_traits<char32_t>
definition, so I gave it a try, and it worked (at least the current program compiled) 1 (and, as expected sizeof(char32_t)
is 4). Then, found [MSDN]: char, wchar_t, char16_t, char32_t
Notes:
wchar_t
, signed char
or char32_t
from unsigned short
for example), so I don't know (yet) why it works for some types but not for others. This is an open topic, whenever I'll get new updates, I will share themBottom line:
As empirically discovered, the following types are allowed, when working with char based STL containers:
char
unsigned char
signed char
wchar_t
char16_t
char32_t
unsigned short
(/Zc:wchar_t-
only )Final note(s):
@EDIT0:
Based on @IgorTandetnik's answer on [MSDN]: Compile error for STL (stream) containers in Visual Studio, although there is still a little bit of fog left on:
unsigned char
and signed char
I'm going to accept this as an answer.