C ++ :: Безопасное использование reinterpret_cast для генерации итераторов-оболочек - PullRequest
1 голос
/ 22 января 2020

У меня есть вектор, содержащий значения заданного примитивного типа, но я хочу перебрать этот вектор так, чтобы я мог выполнять определенные операции «как будто», работая с классом, который переносит тип значения.

В следующем примере кода компилируется и получается ожидаемый результат:

#include <iostream>
#include <vector>

template<class T>
struct wrap 
{
    T x;

    void print() const
    { 
        if (x < 0)
            std::cout << " negative ";
        else if (x > 0)
            std::cout << " positive ";
        else 
            std::cout << " --null-- ";
    }

    void operator ++ ()
    {
        if (this->x <  static_cast<T>(0))
            this->x += static_cast<T>(1000);
    }
};


int main() 
{
    using vec_t = std::vector<int>;
    vec_t v;
    v.push_back(-1234);
    v.push_back( 5678);
    v.push_back(-4);
    v.push_back(0);

    // essential piece of code
    using vec_w = std::vector< wrap<int> >;
    vec_w::iterator it = reinterpret_cast<vec_w*>(&v)->begin();
    vec_w::iterator ti = reinterpret_cast<vec_w*>(&v)->end();

    while (it != ti)
    {
        it->print();
        ++(*it);
        it->print();
        std::cout << std::endl;
        ++it;
    }

    return 0;
}

Вывод:

 negative  negative 
 positive  positive 
 negative  positive 
 --null--  --null-- 

Но безопасно ли это использовать, если оболочка определяет точно такой же тип значения (и больше ничего)?

1 Ответ

2 голосов
/ 22 января 2020

Но безопасно ли это использовать, если оболочка определяет точно такой же тип значения (и ничего больше)?

Нет. Вы нарушаете строгое правило наложения имен.

Почему бы не обернуть T&?

template<class T>
struct wrap 
{
    T& x;

    void print() const
    { 
        if (x < 0)
            std::cout << " negative ";
        else if (x > 0)
            std::cout << " positive ";
        else 
            std::cout << " --null-- ";
    }

    void operator ++ ()
    {
        if (this->x <  static_cast<T>(0))
            this->x += static_cast<T>(1000);
    }
};

Вы можете обернуть в al oop

int main() 
{
    std::vector<int> v;
    v.push_back(-1234);
    v.push_back( 5678);
    v.push_back(-4);
    v.push_back(0);

    for (auto & i : v)
    {
        wrap<int> w { i };
        w.print();
        ++w;
        w.print();
        std::cout << std::endl;
    }

    return 0;
}

Или иметь вектор обернутый

int main() 
{
    std::vector<int> v;
    v.push_back(-1234);
    v.push_back( 5678);
    v.push_back(-4);
    v.push_back(0);

    std::vector<wrap<int>> w { v.begin(), v.end() };

    for (auto & i : w)
    {
        i.print();
        ++i;
        i.print();
        std::cout << std::endl;
    }

    return 0;
}
...