upper_bound с бинарной функцией Visual Studio 2008 Ошибка?

Во-первых, да, я застрял в Visual Studio 2008 и считаю, что эта ошибка характерна для Visual Studio 2008.

Я пытаюсь написать функтор, чтобы сравнить только 1 член моей структуры, чтобы я мог сделать upper_bound на vector из указанных структур, которые отсортированы по этому члену. Это сложно объяснить словами, вот пример:

struct Foo {
    int a;
    char b;
};

struct comp : binary_function<const double, const Foo&, bool> {
    bool operator () (const double lhs, const Foo& rhs) { return lhs < rhs.a; }
};

int main() {
    vector<Foo> test;

    for(int i = 0; i < 5; ++i) {
        Foo foo = { i + 1, 'a' + i };

        test.push_back(foo);
    }

    cout << upper_bound(test.begin(), test.end(), 2, comp())->b << endl;
}

Это прекрасно работает на Visual Studio 2015. Но Visual Studio 2008 выдает мне ошибку:

ошибка C2664: "bool comp::operator ()(const double,const Foo &)": невозможно преобразовать параметр 1 из "Foo" в "const double"

Я подозреваю, что в реализации есть какое-то зло, когда функтор проверяется на строго слабое упорядочение путем замены входных данных. Есть ли обходной путь, чтобы приостановить эту проверку на компиляторе, или мне просто нужно просто поменять свой функтор на 2? Fooи сделать временный Foo представлять 2 здесь?

2 ответа

Решение

Как утверждает Альгирдас Преиджюс, это ошибка реализации только для отладки в Visual Studio 2008. Она была исправлена ​​в /questions/tagged/visual-studio-2010.

Ошибка в коде реализации Microsoft C++, и она устраняется _HAS_ITERATOR_DEBUGGING поэтому, если вы отключите эту опцию, попробуйте добавить "_HAS_ITERATOR_DEBUGGING=0" в "Определения препроцессора".

Если вам не нравится идея отключения проверки итератора, вам нужно обойти это путем отключения _HAS_ITERATOR_DEBUGGING поэтому ваш код будет выглядеть примерно так:

struct Foo {
    int a;
    char b;
};

int main() {
    vector<Foo> test;

    for(int i = 0; i < 5; ++i) {
        Foo foo = { i + 1, 'a' + i };

        test.push_back(foo);
    }

#if _HAS_ITERATOR_DEBUGGING
    for(vector<Foo>::const_iterator it = test.begin(); it != test.end(); ++it) {
        if(it->a > 2) {
            cout << it->b << endl;
            break;
        }
    }
#else
    struct comp : public binary_function<const double, const Foo&, bool> {
        bool operator () (const double lhs, const Foo& rhs) { return lhs < rhs.a; }
    };

    cout << upper_bound(test.begin(), test.end(), 2, comp())->b << endl;
#endif
}

Пара замечаний здесь:

  1. Обратите внимание, что я использую #if что означает if -блок будет выполняться только если _HAS_ITERATOR_DEBUGGING определен и не равен 0. Во время разработки Visual Studio 2008, кажется, всегда думает, что он не определен
  2. Мой код определяет comp встроенный, если ваша конкретная ситуация требует comp чтобы использовать в нескольких местах 1- й рассмотреть обертывание всего этого else -блок в функции для ограничения количества #define в вашем коде, очевидно, что применимость этого комментария будет ограничена, если вы используете comp в нескольких стандартных алгоритмах

Как уже упоминал Algirdas Preidžius, это из-за строгой проверки слабых заказов.

В качестве обходного пути вы можете определить оба оператора.

struct comp {
    bool operator () (const double lhs, const Foo& rhs) { return lhs < rhs.a; }
    bool operator () (const Foo& lhs, const double rhs) { return lhs.a < rhs; }
};
Другие вопросы по тегам