问题
I'm compiling with g++ 4.4.7 (and can't go any higher currently), and using the -std=gnu++0x
compiler switch, which should allow the syntax of the third line.
typedef std::vector<CI_RecordInfo_Pair> CI_RecordInfo_Vector;
typedef std::vector<std::pair<std::string, CI_RecordInfo_Vector*> > MgrBlks;
MgrBlks mgr_n_blks { {"T2M_NAME", NULL} }; // <--- line 59
However, the compiler complains as follows:
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h: In constructor 'std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = const char (&)[9], _U2 = long int, _T1 = std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _T2 = CI_RecordInfo_Vector*]':
tom.cpp:59: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/bits/stl_pair.h:90: error: invalid conversion from 'long int' to 'CI_RecordInfo_Vector*'
I assume the "long int" is the NULL, and that for some reason I'm unable to convert it to a pointer. Yet elsewhere in a map of structs, I was able to compile something like
foo["X"] = { NULL, "bar", 12 }; // first element is a pointer
What is the difference?
回答1:
The compiler is correct to reject this line:
MgrBlks mgr_n_blks { {"T2M_NAME", NULL} };
In C++11 std::pair
has a template constructor that takes any argument types, then converts them to the members:
template<typename X, typename Y>
pair(X&& x, Y&& y)
: first(std::forward<X>(x)), second(std::forward<Y>(y))
{ }
NULL
must be defined as 0
or 0L
or something similar, so template argument deduction deduces the constructor's template arguments as const char*
and (with GCC) long
. The first argument type is convertible to std::string
but long
is not convertible to CI_RecordInfo_Vector*
, so the constructor cannot be called.
For the other case with a map of structs there is no argument deduction, the RHS of the assignment must be convertible to the struct type, and in that case NULL
is used to directly initialize the struct's first member, rather than first being deduced as a long
and initializing a long
, which cannot be converted to a pointer.
Do not use NULL
in C++11, nullptr
was invented to avoid exactly these problems, you should use it.
A possible workaround would be to cast the argument to the right type:
MgrBlks mgr_n_blks { {"T2M_NAME", (CI_RecordInfo_Vector*)NULL} };
but it's simpler and clearer just to use nullptr
.
来源:https://stackoverflow.com/questions/18217221/c-cant-initialize-a-pointer-in-a-pair-to-null