Вот код, который я недавно написал в VS2012:
///<summary>Lambda: Returns true if the field is significant within a baseline context</summary>
const auto IsSignificantBaselineField = [](const field_info & field)->bool
{
//Some lines removed here!
return something;
};
///<summary>Lambda: Returns true if the field is significant within a project context</summary>
const auto IsSignificantProjectField = [&IsSignificantBaselineField](const field_info & field)->bool
{
if (!IsSignificantBaselineField (field))
return false;
//Some lines removed here!
return something_else;
};
return std::any_of (modified_fields.begin (), modified_fields.end (), (proj_id == 0) ? IsSignificantProjectField : IsSignificantBaselineField);
Как ни странно, когда ‘proj_id = 90000’, IsSignificantProjectField вызывается с помощью std :: any_of, в то время как мое намерение состоит в том, чтобы в этом случае вызывался IsSignificantBaselineField.
Пожалуйста, кто-нибудь может объяснить ошибку в моей логике?
Итак, вот мое предположение, почему код компилируется и показывает поведение, которое вы наблюдаете.
Лямбды оба преобразуются в структуры компилятором.
Один не имеет захватов, и, следовательно, нет членов и конструктор без аргументов.
struct IsSignificantBaselineField_Lambda {
bool operator ()(const field_info & field) { ... }
};
У другого есть один захват, переведенный одному члену и конструктору с одним аргументом.
struct IsSignificantProjectField_Lambda {
IsSignificantProjectField_Lambda(IsSignificantBaselineField_Lambda& capture1)
: m_capture1(capture1) {}
bool operator ()(const field_info & field) {
if (!m_capture1(field)) return false;
...
}
private:
IsSignificantBaselineField_Lambda& m_capture1;
};
Держу пари, что преобразование компилятора не делает этот конструктор explicit
, таким образом, делая его конвертирующим конструктором, что означает, что IsSignificantBaselineField конвертируется в IsSignificantProjectField, и, таким образом, IsSignificantProjectField является общим типом двух. Таким образом, вызов эквивалентен:
return std::any_of (modified_fields.begin (), modified_fields.end (),
(proj_id == 0) ? IsSignificantProjectField :
IsSignificantProjectField_Lambda(IsSignificantBaselineField));
В итоге обе ветви делают одно и то же.
Это конечно ошибка компилятора.
Других решений пока нет …