Clang: problem using bind or mem_fn with string :: c_str and transform

Trying to convert std :: string vector to const char * vector:

#include <algorithm>
#include <functional>
#include <string>
#include <vector>

int main(int argc, char** argv)
{
    std::vector<std::string> values;
    values.push_back("test1");
    values.push_back("test2");
    values.push_back("test3");

    std::vector<const char*> c_values(values.size());

    std::transform(values.begin(), values.end(), c_values.begin(), std::mem_fn(&std::string::c_str));
    std::transform(values.begin(), values.end(), c_values.begin(), std::bind(&std::string::c_str, std::placeholders::_1));
    std::transform(values.begin(), values.end(), c_values.begin(), [](const std::string& str) { return str.c_str(); });

    return 0;
}

When compiling with g ++ (4.7.2), all three parameters are compiled and connected in order. When compiling with clang, parameters 1 and 2 are not connected, producing:

$ clang -std=c++11 -stdlib=libc++ -lc++ stringtransform.cpp 
Undefined symbols for architecture x86_64:
  "std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::c_str() const", referenced from:
    _main in stringtransform-ff30c1.o
ld: symbol(s) not found for architecture x86_64

I find that I need to use the lambda version (option 3) if I want it to bind correctly on different platforms using both g ++ and clang. Am I encountering a linker error or a hole in clang C ++ 11, or is there something wrong with the way I call mem_fn () and bind () versions?

EDIT:

The error is still present on the latest Xcode (6.3.2, with clang version 6.1.0:

$ clang -v
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
+4
3

, lib++, LLVM 3.6.0

, std::string::c_str() DSO, .

&string::c_str - , , . , c_str() , .

, :

#ifdef _LIBCPP_VERSION
template const char* std::string::c_str() const;
#endif

, . 1 2 :

std::mem_fn(&std::string::c_str)
std::bind(&std::string::c_str, std::placeholders::_1)

-, std::basic_string::c_str(), , . , &std::a_class::a_nonvirtual_member_function , , .

, ++ 98-, &std::vector<X>::push_back, ++ 11, ( const lvalue , rvalue).

, , , std::basic_string::c_str .

- , -, :

[](const std::string& str) { return str.c_str(); }

, , -.

+1

: -O .

+1

This is apparently a problem with libC ++.

Considering this,

#include <string>
#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
  string s("Hello, World!");
  const char * (std::string::*mem_c_str) () const = &std::string::c_str;
  cout << (s.*mem_c_str)() << endl;
  return 0;
}

We get the same error.

Fixed with -stdlib=libstdc++ -lstdc++. It seems to work for any flag -On.

0
source

Source: https://habr.com/ru/post/1569230/


All Articles