views:

374

answers:

1

Hi,

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>' (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; }
};
+1  A: 

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<>& parameter). 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).

Michael Burr
Thanks. I seem to be making progress following this reasoning. Currently, I hacked away at the pp_output_iterator and added this operator=:`inline pp_output_iterator ``_M_result.push_back(*__v._M_result.begin());``return *this;``}`(apologies for the lack of formatting)It compiled, but I'm concerned that `*__v._M_result.begin()` is likely wrong. I'll try it for now, but if you (or anyone else) sees anything clearly wrong, please let me know.
guesser
Just an update.. I've replaced the assignment line with `_M_result = __v._M_result;`. I think that makes more sense. Still plugging away at it..
guesser
This fixed my problem -- qtscriptgenerator generated the bindings and it all seems to work. Thank you. I would upvote your answer, but my reputation's too low...........To clarify my comments here.. I replaced the `_M_result.push_back(*__v._M_result.begin());` in my first comment with `_M_result = __v._M_result;`.
guesser
Alright, I'm a newb. I found the little check mark and accepted the answer. Thanks again.
guesser
For anyone else trying to build qtscriptgenerator with Visual Studio who stumbles upon this answer.. I will also mention that during the final stage of building the bindings, I had to hack around a couple 0-sized arrays. To get it to build, comment those out, and also comment out the for-loops that reference them (the for loops typically go from 0 to <0.. so there's no effect anyway).
guesser