Problems with operator= and std::map

1,505 views
Skip to first unread message

Greg Landrum

unread,
Aug 6, 2013, 1:28:35 AM8/6/13
to emscripte...@googlegroups.com
Hi,

I'm just getting started with emscripten and trying to build an open-source C++ project I run (the RDKit: www.rdkit.org).
I've hit some problems with a build that I'm hoping this community can help with.

Here's a minimal code sample that shows the problem:
//-------------------------------------------------
#include <map>
#include <string>

class Dict {
public:
  typedef std::map<const std::string, int> DataType;
  Dict(const Dict &other) {
    _data = other._data;
  };
private:
  DataType _data;
};
//-------------------------------------------------

If I try to build this with em++, I get the following:

/----------------------------------------------------------------------------------------------------------------------------------------------
/scratch/RDKit_git/Code/RDGeneral > /usr/local/src/emscripten/em++  -o blah.obj -c blah.cpp
In file included from blah.cpp:1:
In file included from /usr/local/src/emscripten/system/include/libcxx/map:371:
In file included from /usr/local/src/emscripten/system/include/libcxx/__tree:16:
In file included from /usr/local/src/emscripten/system/include/libcxx/memory:594:
/usr/local/src/emscripten/system/include/libcxx/utility:255:15: error: no viable overloaded '='
        first = __p.first;
        ~~~~~ ^ ~~~~~~~~~
/usr/local/src/emscripten/system/include/libcxx/__tree:1246:35: note: in instantiation of member function
      'std::__1::pair<const std::__1::basic_string<char>, int>::operator=' requested here
                __cache->__value_ = *__first;
                                  ^
/usr/local/src/emscripten/system/include/libcxx/__tree:1187:9: note: in instantiation of function template
      specialization 'std::__1::__tree<std::__1::pair<const std::__1::basic_string<char>, int>,
      std::__1::__map_value_compare<const std::__1::basic_string<char>, int, std::__1::less<const
      std::__1::basic_string<char> >, true>, std::__1::allocator<std::__1::pair<const
      std::__1::basic_string<char>, int> >
      >::__assign_multi<std::__1::__tree_const_iterator<std::__1::pair<const std::__1::basic_string<char>,
      int>, const std::__1::__tree_node<std::__1::pair<const std::__1::basic_string<char>, int>, void *> *,
      int> >' requested here
        __assign_multi(__t.begin(), __t.end());
        ^
/usr/local/src/emscripten/system/include/libcxx/map:766:21: note: in instantiation of member function
      'std::__1::__tree<std::__1::pair<const std::__1::basic_string<char>, int>,
      std::__1::__map_value_compare<const std::__1::basic_string<char>, int, std::__1::less<const
      std::__1::basic_string<char> >, true>, std::__1::allocator<std::__1::pair<const
      std::__1::basic_string<char>, int> > >::operator=' requested here
            __tree_ = __m.__tree_;
                    ^
blah.cpp:8:11: note: in instantiation of member function 'std::__1::map<const std::__1::basic_string<char>,
      int, std::__1::less<const std::__1::basic_string<char> >, std::__1::allocator<std::__1::pair<const
      std::__1::basic_string<char>, int> > >::operator=' requested here
    _data = other._data;
          ^
/usr/local/src/emscripten/system/include/libcxx/string:1174:19: note: candidate function not viable: 'this'
      argument has type 'const std::__1::basic_string<char>', but method is not marked const
    basic_string& operator=(const basic_string& __str);
                  ^
/usr/local/src/emscripten/system/include/libcxx/string:1181:45: note: candidate function not viable: 'this'
      argument has type 'const std::__1::basic_string<char>', but method is not marked const
    _LIBCPP_INLINE_VISIBILITY basic_string& operator=(const_pointer __s) {return assign(__s);}
                                            ^
/usr/local/src/emscripten/system/include/libcxx/string:1182:19: note: candidate function not viable: 'this'
      argument has type 'const std::__1::basic_string<char>', but method is not marked const
    basic_string& operator=(value_type __c);
                  ^
1 error generated.
ERROR    root: compiler frontend failed to generate LLVM bitcode, halting
/----------------------------------------------------------------------------------------------------------------------------------------------

Adding -m32 to the emscripten command line gives the same error.

clang++ works fine:

/----------------------------------------------------------------------------------------------------------------------------------------------
/scratch/RDKit_git/Code/RDGeneral > /usr/local/bin/clang++  -o blah.obj -c blah.cpp
/scratch/RDKit_git/Code/RDGeneral > 
/----------------------------------------------------------------------------------------------------------------------------------------------

Changing the typedef to:
  typedef std::map<std::string, int> DataType;
allows emscripten to build the code, but I'm pretty sure that this shouldn't be necessary.

I did a git pull this morning for emscripten and am using clang++ v3.2 on a 64-bit ubuntu 12.04 system.

Am I doing something wrong or is this a bug?

Thanks,
-greg

Alon Zakai

unread,
Aug 6, 2013, 1:28:05 PM8/6/13
to emscripte...@googlegroups.com
This looks like a problem with libc++, the c++ standard library emscripten uses. clang also hits the problem when using libc++ instead of the system c++ standard lib,

clang++ a.cpp -c -nostdinc++ -Isystem/include/libcxx

I would test if the latest upstream libc++ also fails on this error (http://libcxx.llvm.org/ ). If it does, i would file a bug there. If it works, then we need to update libc++ in emscripten.

- Alon




--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Greg Landrum

unread,
Aug 6, 2013, 3:39:17 PM8/6/13
to emscripte...@googlegroups.com
Hi Alon,


On Tuesday, August 6, 2013 7:28:05 PM UTC+2, azakai wrote:
This looks like a problem with libc++, the c++ standard library emscripten uses. clang also hits the problem when using libc++ instead of the system c++ standard lib,

clang++ a.cpp -c -nostdinc++ -Isystem/include/libcxx

I would test if the latest upstream libc++ also fails on this error (http://libcxx.llvm.org/ ). If it does, i would file a bug there. If it works, then we need to update libc++ in emscripten.


Thanks for the reply.

I just pulled a copy of libc++ from svn and tried running clang++ using that. Things work:

/scratch/RDKit_git/Code/RDGeneral > /usr/local/bin/clang++  -I /usr/local/src/libcxx_svn/include -o blah.obj -c blah.cpp
/scratch/RDKit_git/Code/RDGeneral > 

The next logical test is to use em++ against the same directory. That's also fine:
/scratch/RDKit_git/Code/RDGeneral > /usr/local/src/emscripten/em++  -I /usr/local/src/libcxx_svn/include -o blah.obj -c blah.cpp
/scratch/RDKit_git/Code/RDGeneral >

Adding -I/usr/local/src/libcxx_svn/include to the build flags for my project also seems to have helped get more of it built.

Looks like an update of libc++ for emscripten would help.

Best,
-greg

Bruce Mitchener

unread,
Aug 8, 2013, 5:06:32 AM8/8/13
to emscripte...@googlegroups.com
On Wed, Aug 7, 2013 at 3:39 AM, Greg Landrum <greg.l...@gmail.com> wrote:
Looks like an update of libc++ for emscripten would help.

I needed one as well, so:


 - Bruce

Erik

unread,
Aug 8, 2013, 4:08:18 PM8/8/13
to emscripte...@googlegroups.com
I am not being mean, but its bad code.  I cant tell you the number of times I get into troubles trying to use standard = operators for STL containers across various compilers.

1)  Try and use the initializer list, not the body of the constructor.  Your code is constructing an empty Dict then trying to reinitialize it with the = operator.  

Wrong way

  Dict(const Dict &other) {
    _data = other._data;
  };

Right way (use copy constructor)
Dict(const Dict &other) : _data(other._data)  { };

2) For copying stl containers to other stl containers of constructors use std::copy

Example for the std::map
std::copy( sourceMap.begin(), sourceMap.end(), std::inserter(destinationMap, destinationMap.begin()) );

Example for the std::vector
std::copy(sourceVector.begin(), sourceVector.end(), std::back_inserter(destinationVector));

I NEVER use = operators for STL containers because I have been bitten many times in the past.  Works on 1 compiler and fails on others.  Very painful.
Reply all
Reply to author
Forward
0 new messages