У меня есть такой код:

#include <set>
#include <vector>

struct Comp {
    const std::vector<int> & xs;

    Comp(const std::vector<int> & xs): xs(xs) {}

    bool operator(int a, int b) const {
        // Sort based on data in xs.
    } 
};

class Foo {

public:
    Foo();

private:
    std::vector<int> xs;
    std::set<std::size_t, Comp(xs)> ys;

};

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

Каждый раз, когда я обновляю значение в векторе, я erase, а затем insert индексирую, который соответствует значению в векторе, чтобы также обновлять набор.

Сейчас я получаю сообщение об ошибке: error: invalid use of non-static data member 'xs'. Как лучше всего достичь того, чего я хочу?

c++
0
philhimself 10 Фев 2021 в 20:05

1 ответ

Лучший ответ

Вы можете указать ссылку на xs на Comp и Comp на ys

  • в списке инициализации членов конструктора
  • или один раз и навсегда, если объявлен член ys.

!!! если вы измените содержимое xs, пока ys не пусто, то ys непременно станет непригодным для использования !!!

В этой адаптации вашего кода вы можете видеть, что ys упорядочен в соответствии с xs.

/**
  g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
      -pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#include <iostream>

#include <set>
#include <vector>

struct Comp {
    const std::vector<int> & xs;

    Comp(const std::vector<int> & xs): xs(xs) {}

    bool operator()(int a, int b) const {
        return size(xs)%2==0 ? a<b : b<a; // Sort based on data in xs.
    } 
};

class Foo {

public:
    Foo(std::vector<int> v)
    : xs{std::move(v)}
    , ys{Comp{xs}}
    {}

// private:

    std::vector<int> xs;
    std::set<int, Comp> ys;
    // std::set<int, Comp> ys{Comp{xs}}; // or once for all
};

int
main()
{
  auto f1=Foo{{1, 2, 3}};
  for(auto i=0; i<20; ++i)
  {
    f1.ys.insert(i%7);
  }
  for(const auto &e: f1.ys) { std::cout << e << ' '; } std::cout << '\n';

  auto f2=Foo{{1, 2, 3, 4}};
  for(auto i=0; i<20; ++i)
  {
    f2.ys.insert(i%7);
  }
  for(const auto &e: f2.ys) { std::cout << e << ' '; } std::cout << '\n';
  return 0;
}
/*
6 5 4 3 2 1 0 
0 1 2 3 4 5 6 
*/
2
prog-fh 10 Фев 2021 в 17:50