views:

267

answers:

1

I was just poking around into some new stuff in C++0x, when I hit a stumbling block:

#include <list>
#include <cstdio>
using namespace std;

template <typename T,typename F>
void ForEach (list<T> l, F f) {
    for (typename list<T>::iterator it=l.begin();it!=l.end();++it)
        f(*it);
}

int main() {
    int arr[] = {1,2,3,4,5,6};
    list<int> l (arr,arr+6);
    ForEach(l,[](int x){printf("%d\n",x);});
}

does not compile. I get a load of undefined symbol errors. Here's make's output:

 i386-apple-darwin9-gcc-4.5.0 -std=c++0x -I/usr/local/include -o func main.cpp
Undefined symbols:
  "___cxa_rethrow", referenced from:
      std::_List_node<int>* std::list<int, std::allocator<int> >::_M_create_node<int const&>(int const&&&) in ccPxxPwU.o
  "operator new(unsigned long)", referenced from:
      __gnu_cxx::new_allocator<std::_List_node<int> >::allocate(unsigned long, void const*) in ccPxxPwU.o
  "___gxx_personality_v0", referenced from:
      ___gxx_personality_v0$non_lazy_ptr in ccPxxPwU.o
  "___cxa_begin_catch", referenced from:
      std::_List_node<int>* std::list<int, std::allocator<int> >::_M_create_node<int const&>(int const&&&) in ccPxxPwU.o
  "operator delete(void*)", referenced from:
      __gnu_cxx::new_allocator<std::_List_node<int> >::deallocate(std::_List_node<int>*, unsigned long) in ccPxxPwU.o
  "___cxa_end_catch", referenced from:
      std::_List_node<int>* std::list<int, std::allocator<int> >::_M_create_node<int const&>(int const&&&) in ccPxxPwU.o
  "std::__throw_bad_alloc()", referenced from:
      __gnu_cxx::new_allocator<std::_List_node<int> >::allocate(unsigned long, void const*) in ccPxxPwU.o
  "std::_List_node_base::_M_hook(std::_List_node_base*)", referenced from:
      void std::list<int, std::allocator<int> >::_M_insert<int const&>(std::_List_iterator<int>, int const&&&) in ccPxxPwU.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [func] Error 1

Why is this not working?

+5  A: 

Those are link errors. Are you missing a C++ library? What if you used i386-apple-darwin9-g++-4.5.0?

P.S. I can't test this, as I have gcc 4.2.1 (i686-apple-darwin10-gcc-4.2.1) on my Mac and get:

cc1plus: error: unrecognized command line option "-std=c++0x"
Mike DeSimone
`C++0x` support requires a VERY new version of `g++`. But your suggestion of `g++` instead of `gcc` probably hits the nail on the head.
Ben Voigt
How would it get to the linker stage if gcc weren't recognizing it as a C++ source file?
Dennis Zickefoose
Well, however it gets to the link stage, that is probably the problem. I get the exact same errors when compiling my c++0x code with gcc instead of g++ with 4.5.
Dennis Zickefoose
Any time you see `Undefined symbols: ... "operator new(unsigned long)"`, you need to *immediately* think, "My C++ standard library is not being linked in. It thinks I'm building a C program."
Mike DeSimone
@Dennis: For most programs, the compile and link steps are separate commands. You run a compile process for each source file, and when you're done, you take all the objects and link them. While `gcc` is fully capable of telling when it is fed C++ source at *compile* time by looking at the suffix, this information is discarded as soon as compilation completes, prior to linking, because all compiled files get the same suffix: `.o`.
Mike DeSimone
When you use `gcc` to compile *and* link, it does this exact same two-stage process, just internally, and adds no special "hinting" to the link stage. If it didn't work this way, then things that compile in one `gcc` call would fail to compile in separate compile and link stages, which would be surprising behavior (and another FAQ on SO). So they chose to have the link stage assume nothing about its inputs in all cases.
Mike DeSimone