Можно ли связать две изменяемые переменные вместе?

Примере:

class foo{
public:
     std::vector<int> v1;
     std::vector<float> v2;

     //Imaginary Code here:
     void on_v2_change(){
          std::transform(begin(v2),end(v2),begin(v1),[](auto& item){ return std::round(item);});
     }
}

int main(){
    foo bar;
    bar.v2.push_back(5.7);
    //v2={5.4}
    //v1={5}
}

Есть ли простой способ реализовать предыдущее? что-то вроде событий Java или C #.

1
Humam Helfawi 24 Дек 2015 в 10:32

4 ответа

Лучший ответ

Вы можете написать обертку с событиями, например:

template<typename V>
class vector_observer
{
    virtual ~vector_observer() = default;
    virtual void on_push_back(typename V::const_reference value) = 0;
    virtual void on_clear() = 0;
    // ...
};

template<typename T>
class observed_vector
{
private:
    std::vector<T> vec;
    vector_observer& obs;
public:
    explicit observed_vector(vector_observer& obs) : obs(obs) {}

    void push_back(const T& value) { vec.push_back(value); obs.on_push_back(value); }
    void clear() { vec.clear(); obs.on_clear(); }
    // ...
};

А также

class to_int_vector_observer : public vector_observer<std::vector<float>>
{
public:
    explicit to_int_vector_observer(std::vector<int>&vec) : vec(vec) {}

    void on_push_back(float value) override{ vec.push_back(round(value)); }
    void on_clear() override { vec.clear(); }

private:
    std::vector<int>& vec;
}
1
Jarod42 24 Дек 2015 в 10:15

Хотя отвлечение оператора () не является решением, очень совместимым с C ++ ...

#include "stdafx.h"
#include <vector>

class vectorFloatAndInt : public std::vector<float>
{
public:
    inline int operator () (unsigned int paramPos)
    {
         return std::round((*this)[paramPos]);
    }
};

int main()
{
   vectorFloatAndInt bar;
   bar.push_back(5.4);

   float vf = bar[0];    // == 5.4
   int vi = bar(0);      // == 5
   return 0;
}
0
noname 24 Дек 2015 в 09:56

Используя шаблонный класс и функцию, сделайте универсальным и преобразуйте ввод во время передачи в качестве аргумента.

#include <iostream>
#include <vector>

template <class T1, class T2>
class Stack {
  private:
    std::vector<T1> v1;
    std::vector<T2> v2;

  public:
  template<typename T3, typename T4>
  void push (T3 v,  T4 flag) {
    if(flag)
        v1.push_back(v);
    else
        v2.push_back(v);
  }
};

int main() {
  Stack<int,float> stack;
  stack.push(7,0);
  stack.push((int)7.5,1);
}

Или, кроме того, его можно изменить в соответствии с требованиями, например, преобразование float -> int может быть выполнено в методе push в соответствии с использованием и дизайном.

0
Prashant Singh 24 Дек 2015 в 09:49

Я не знаю, можете ли вы использовать именно этот синтаксис, но вы можете использовать следующее:

class foo {
    std::vector<int> v1;
    std::vector<float> v2;

    public:
    void push_back(float val) {
        v1.push_back(std::round(val));
        v2.push_back(val);
    }
    // ....

Вы также можете добавить аналогичные функции для других функций (например, erase ()). Насколько мне известно, другого способа изменить сразу два вектора нет.

2
thefunkyjunky 24 Дек 2015 в 07:39