Сравнение переменных, которые хранятся в шаблонном классе

Название вопроса сложно сформулировать. Задача следующая, есть некоторая обертка:

struct IVar
{
    virtual value_t get() const = 0;
};

template<typename V>
class Var : public IVar
{
    V& var_;
public:
    Var(V& var) : var_(var) {}
    value_t get() const override { return some_value; }
};

Далее создаем вектор и заполняем его:

int a{};
double b{};

std::vector<std::unique_ptr<IVar>> Vec{};

Vec.push_back(std::make_unique<Var<decltype(a)>>(a));
Vec.push_back(std::make_unique<Var<decltype(b)>>(b));

Vec.push_back(std::make_unique<Var<decltype(a)>>(a)); // запретить повторное создание 

Нужен совет, каким образом убедиться, что для переменной уже создана обертка?


Ответы (1 шт):

Автор решения: isnullxbh

Вы можете добавить в IVar метод, который возвращает указатель на void, и использовать его для сравнения Var<T> объектов. Но нужно иметь ввиду, что в некоторых случаях это будет работать некорректно, ниже приведу кейс.

struct IVar
{
    using Ptr = std::unique_ptr<IVar>;
    virtual ~IVar() = default;
    virtual void* address() const noexcept = 0;
    // ...
};

И, соответственно, для списка нужна некоторая обертка, чтобы у Вас была возможность выполнять проверку на уникальность:

class UniqueVarList
{
public:
    template<typename T>
    bool add(T& value) { /* ... */ }

private:
    std::vector<IVar::Ptr> _items {};
};

Пример кода.


Пример потенциально нежелательного поведения:

struct A { virtual void foo() {} virtual ~A() = default; };
struct B { virtual void boo() {} virtual ~B() = default;};
struct C : A, B {};

UniqueVarList l;
std::cout << std::boolalpha
          << "Added? " << l.add(c) << '\n'
          << "Added? " << l.add(static_cast<A&>(c)) << '\n'
          << "Added? " << l.add(static_cast<B&>(c))
          << std::endl;

Вывод:

Added? true
Added? false
Added? true

→ Ссылка