У меня странная проблема (здесь я упростил код) с clang 3.1 (gcc работает нормально).
Это неправильное использование std :: function (передается по значению) или ошибка clang?
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;
}
Я использую Apple clang 4.1 (llvm 3.1) на Max OS X Lion.
Если я изменяю тип второго параметра на что-то другое (например, int), все работает нормально.
Если я создаю объект A непосредственно из ctor, вместо использования фабрики ‘make’, все работает нормально.
Я действительно не могу понять, является ли это лягушатником или моим недоразумением.
Вы передаете string
по значению в конструкторе A
, а затем создание итератора в локальной строке. Строка затем уничтожается в конце конструктора, оставляя вас с недопустимым итератором и неопределенным поведением.
//`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_; }
Других решений пока нет …