Reputation: 115
I'm having this strange issue (I've simplified the code here) with clang 3.1 (gcc works fine). Is it improper use of std::function (passed by value) or a clang bug?
template <typename Container>
struct A
{
using function_type = std::function<char(char)>;
A(Container c, function_type f) : it_(c.begin()), f_(f) {}
typename Container::value_type operator*() { return *it_; }
typename Container::iterator it_;
function_type f_;
};
template <typename Cont>
A<Cont> makeA(Cont c, std::function<char(char)> f)
{
return A<Cont>(c, f);
}
char f(char ch) { return ch; }
int main()
{
std::string s { "foo" };
auto a = makeA(s, f); // wraps s.begin()
std::clog << "main: " << *(s.begin()) << std::endl; // prints 'f'
std::clog << "main: " << *a << std::endl; // prints garbage
return 0;
}
I'm using Apple clang 4.1 (llvm 3.1) on Max OS X Lion.
If I change the type of the second parameter to something else (such as int), everything works fine.
If I construct the A object directly from the ctor, instead of using the 'make' factory, everything works fine.
I really can't understand whether it's a clang bug or my misunderstanding.
Upvotes: 2
Views: 320
Reputation: 40633
You are passing the string
by value in to the constructor of A
, and then creating an iterator in to the local string. The string is then destroyed at the end of the constructor, leaving you with an invalid iterator and undefined behavior.
//`c` is a local copy of the string
A(Container c, function_type f) :
//c.begin() returns an iterator into `c`
it_(c.begin()),
f_(f)
{
}//`c` is destroyed, leaving it_ as a dangling iterator
//Dereferences `it_` -- undefined behaviour
typename Container::value_type operator*() { return *it_; }
Upvotes: 6