STL operator= behavior change with Visual Studio 2010?
I am attempting to compile QtScriptGenerator (gitorious) with Visual Studio 2010 (C++) and have run into a compile error. In searching for a solution, I have seen occasional references to compile breakages introduced since VS2008 due to changes in VS2010's implementation of STL and/or c++0x conformance changes.
Any ideas what is happening below, or how I could go about fixing it? If the offending code appeared to be QtScriptGenerator's, I think I would have an easier time fixing it.. but it appears to me that the offending code may be in VS2010's STL implementation and I may be required to create a workaround?
PS. I am pretty unfamiliar with templates and STL. I have a background in embedded and console projects where such things have until recently often been avoided to reduce memory consumption and cross-compiler risks.
Edit - It appears it is probably Visual Studio's implementation of std::copy which changed.
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xutility(275) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'rpp::pp_output_iterator<_Container开发者_如何学JAVA>' (or there is no acceptable conversion)
with
[
_Container=std::string
]
c:\qt\qtscriptgenerator\generator\parser\rpp\pp-iterator.h(75): could be 'rpp::pp_output_iterator<_Container> &rpp::pp_output_iterator<_Container>::operator =(const char &)'
with
[
_Container=std::string
]
while trying to match the argument list '(rpp::pp_output_iterator<_Container>, rpp::pp_output_iterator<_Container>)'
with
[
_Container=std::string
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xutility(2176) : see reference to function template instantiation '_Iter &std::_Rechecked<_OutIt,_OutIt>(_Iter &,_UIter)' being compiled
with
[
_Iter=rpp::pp_output_iterator<std::string>,
_OutIt=rpp::pp_output_iterator<std::string>,
_UIter=rpp::pp_output_iterator<std::string>
]
c:\qt\qtscriptgenerator\generator\parser\rpp\pp-internal.h(83) : see reference to function template instantiation '_OutIt std::copy<std::_String_iterator<_Elem,_Traits,_Alloc>,_OutputIterator>(_InIt,_InIt,_OutIt)' being compiled
with
[
_OutIt=rpp::pp_output_iterator<std::string>,
_Elem=char,
_Traits=std::char_traits<char>,
_Alloc=std::allocator<char>,
_OutputIterator=rpp::pp_output_iterator<std::string>,
_InIt=std::_String_iterator<char,std::char_traits<char>,std::allocator<char>>
]
c:\qt\qtscriptgenerator\generator\parser\rpp\pp-engine-bits.h(500) : see reference to function template instantiation 'void rpp::_PP_internal::output_line<_OutputIterator>(const std::string &,int,_OutputIterator)' being compiled
with
[
_OutputIterator=rpp::pp_output_iterator<std::string>
]
C:\Program Files\Microsoft Visual Studio 10.0\VC\INCLUDE\xutility(275) : error C2582: 'operator =' function is unavailable in 'rpp::pp_output_iterator<_Container>'
with
[
_Container=std::string
]
Here's some context..
pp-internal.h
#ifndef PP_INTERNAL_H
#define PP_INTERNAL_H
#include <algorithm>
#include <stdio.h>
namespace rpp {
namespace _PP_internal
{
..
64 template <typename _OutputIterator>
65 void output_line(const std::string &__filename, int __line, _OutputIterator __result)
66 {
67 std::string __msg;
68
69 __msg += "# ";
70
71 char __line_descr[16];
72 pp_snprintf (__line_descr, 16, "%d", __line);
73 __msg += __line_descr;
74
75 __msg += " \"";
76
77 if (__filename.empty ())
78 __msg += "<internal>";
79 else
80 __msg += __filename;
81
82 __msg += "\"\n";
83 std::copy (__msg.begin (), __msg.end (), __result);
84 }
pp-engine-bits.h
#ifndef PP_ENGINE_BITS_H
#define PP_ENGINE_BITS_H
#include <stdio.h>
namespace rpp {
450 template <typename _InputIterator, typename _OutputIterator>
451 void pp::operator () (_InputIterator __first, _InputIterator __last, _OutputIterator __result)
452 {
..
497 if (env.current_line != was)
498 {
499 env.current_line = was;
500 _PP_internal::output_line (env.current_file, env.current_line, __result);
501 }
.. and here's the definition of pp_output_iterator
pp-iterator.h
#ifndef PP_ITERATOR_H
#define PP_ITERATOR_H
#include <iterator>
namespace rpp {
..
template <typename _Container>
class pp_output_iterator
: public std::iterator<std::output_iterator_tag, void, void, void, void>
{
std::string &_M_result;
public:
explicit pp_output_iterator(std::string &__result):
_M_result (__result) {}
inline pp_output_iterator &operator=(typename _Container::const_reference __v)
{
if (_M_result.capacity () == _M_result.size ())
_M_result.reserve (_M_result.capacity () << 2);
_M_result.push_back(__v);
return *this;
}
inline pp_output_iterator &operator * () { return *this; }
inline pp_output_iterator &operator ++ () { return *this; }
inline pp_output_iterator operator ++ (int) { return *this; }
};
I think that the problem is that std::copy
is trying to use 'copy assignment' (operator=()
) on your rpp::pp_output_iterator<>
and there is no operator=()
for that class template. I should say, there is an operator=()
but it doesn't take the correct parameter to be the 'copy assignment' function (ie., it doesn't take a ``rpp::pp_output_iterator<>¶meter). I think that the existence of some
operator=()` function will prevent the compiler from generating a default (I don't have access to the standard document at the moment to verify this 100%).
Note that a type must be assignable (among other things, of course) to be considered an OutputIterator: http://www.sgi.com/tech/stl/OutputIterator.html
Previous versions of std::copy
in MSVC might not have actually used assignment (just because OutputIterator must support it doesn't mean std::copy
has to use it), which is why it might be a 'new' error in VS2010. (I can't check right now due to limited access to my tools).
I added these code to pp-iterator.h for template class pp_output_iterator, and can fix this issue:
inline pp_output_iterator &operator=(const typename pp_output_iterator<_Container>& __v)
{
_M_result = __v._M_result;
return *this;
}
I had this same problem. The things guesser is saying here did not make much sense to me against the code I got from the git repo (head on 4.7.2011), so I went around this in another way.
This problem is only in the generator project that make a generator that produces the generated code that is utilized by the qtbindings project. The simple fact is that you don't have to use VC10 to build the generator, you can use Qt provided VC9 build to make the generator this will not produce the OP mentioned build errors.
Before running the generator: Remember to change QTDIR to the VC10 Qt build you want the bindings against, or I guess that doesn't matter anyways if the version number is the same. The generator.exe will be built in the release folder, copy that and QtCore and QtXml dll:s to the parent folder from your VC9 Qt that you built the generator against.
After this build the qtbindings project with VC10. I had some minor problems there like it had linker output extensions as .lib, just change all of those to .dll and it should go trough.
Hope this helps people if they have probs with this in the future as Visual Studio 10 gets more traction :) Hopefully the maintainers will fix the build error at some point.
精彩评论