LINUX.ORG.RU

vectror<const A*>

 


0

2

Как превратить vectror<A*> в const vectror<const A*>?

Работает и создание нового вектора, и reintrtpret_cast.

Насколько он безопасен в данном случае?

#include <vector>
#include <memory>
#include <iostream>
using namespace std;

class A
{
	int n = 1;
public:
	explicit A(int nn)
		:n(nn){}

	~A(){}

	void foo()
	{
		cout << "A:" << n << endl;
	}
	
	void foo() const
	{
		cout << "A const:" << n << endl;
	}
};


class B
{
	vector<shared_ptr<A>> vspa;
public:
	B()
	{
		for (auto& i : { 1,2,3,4,5,6,7,8,9,10 })
		{
			vspa.push_back(make_shared<A>(i));
		}
	}

	~B(){}

	const vector<shared_ptr<const A>> get_vspca() const
	{
		return vector<shared_ptr<const A>>(vspa.begin(), vspa.end());
		//safe, require vector construction and shared_ptr ref_count++
	}

	const vector<shared_ptr<const A>>& get_crvspca() const
	{
		return reinterpret_cast<const vector<shared_ptr<const A>>&>(vspa);
		//unsafe(?) but transparent
	}
};

void bar(const vector<shared_ptr<const A>>& vv)
{
	for (auto& i : vv)
	{
		i->foo();
		cout << "^use_count: " << i.use_count() << endl;
	}
	cout << "======" << endl;
}

int main(int argc, char* argv[])
{
	const B bb;

	bar(bb.get_vspca());
	bar(bb.get_crvspca());

	return 0;
}

в чем смысл данного ужаса?

anonymous ()
Ответ на: комментарий от anonymous

Нет особо прикладного смысла. Отдать вектор указателей, с гарантией неизменения объектов по этим указателям.

Uter ()

Как превратить vectror<A*> в const vectror<const A*>?

#include <vector>
using std::vector;

int main() {
    vector<int*>        vm { 0, 0, 0 };
    vector<const int*>  vi { vm.begin(), vm.end() };
}

И не переживай за скорость, вероятность, что это будет узким местом - крайне мала (с).

anonymous ()

Что в твоем понятии unsafe?

mix_mix ★★★★★ ()

reinterpret_cast это молот тора в хрустальной лавке, к тому же он тоже создает новый prvalue объект

anonymous ()
Ответ на: комментарий от mix_mix

Хмм.

Как сказали - reinterpret_cast почти всегда в той или иной мере небезопасен.

Например, небезопасно было бы делать так, поскольку позволяет добавить в вектор shared_ptr<const A>, и внутри класса B работать с shared_ptr<A>

	vector<shared_ptr<const A>>& get_rvspca() const
	{
		return reinterpret_cast<vector<shared_ptr<const A>>&>(vspa);
	}

Преобразование же в ссылку на const vector<shared_ptr<const A>> мне кажется безопасным, и я хочу знать, так ли это, нет ли при этом еще потенциальных проблем,

Uter ()
Ответ на: комментарий от Uter

International Standard ISO/IEC 14882:2014(E) Programming Language C++»

5.2.10 Reinterpret cast ... 2 The reinterpret_cast operator shall not cast away constness. ...

//thread

anonymous ()
Ответ на: комментарий от anonymous

у автора не away, а наоборот. К тому же это утверждение относится к типу операнда, а не к типу темплейт параметра. Что конечно не отменяет в целом неопределенного поведения такого преобразования.

anonymous ()
Ответ на: комментарий от Uter

и я хочу знать, так ли это, нет ли при этом еще потенциальных проблем,

Идея мне не нравится, хотя формально запрета может и нет. У нас используется обёртка, в таких случаях.

DarkEld3r ★★★★★ ()
Ответ на: комментарий от anonymous

Эм...

vector<const int*>  vi { vm.begin(), vm.end() };

А разве допустим initializer list в виде пары итераторов? У меня все доступные мне компиляторы ругаются.

Тут же надо просто конструктор:

vector<const int*>  vi( vm.begin(), vm.end() );
grondek ()
Ответ на: комментарий от grondek

Тут же надо просто конструктор:

А это и будет просто конструктор. Фигурные скобки - это не только «initializer list», а ещё и «uniform initialization».

DarkEld3r ★★★★★ ()
Ответ на: комментарий от anonymous

Ъ-С++-way это по идее можно реализовать следующим образом:

Из bar сделать шаблонную функцию, принимающую пару итераторов. Она может делать static_assert на то, что тип аргумента, возвращаемого итератором это const A*

Далее пара vector<A*>::const_iterator при помощи performance-free обёртки boost::transform_iterator преобразуется в пару итераторов возвращающих уже не A*, а const A* и передаётся в bar.

	const vector<shared_ptr<const A>>& get_crvspca() const
	{
		return reinterpret_cast<const vector<shared_ptr<const A>>&>(vspa);
		//unsafe(?) but transparent
	}

А это не будет работать в абстрактном микрокомпьютере, где ram 16-битный, а rom 32-битный, и поэтому константные указатели занимают 4 байта, а неконстантные 2.

GPFault ()
Ответ на: комментарий от GPFault

Далее пара vector<A*>::const_iterator при помощи performance-free обёртки boost::transform_iterator преобразуется в пару итераторов возвращающих уже не A*, а const A* и передаётся в bar.

Но там же на самом деле shared_ptr<A> и он не преобразуется в shared_ptr<const A> без дерганья счетчика.

А это не будет работать в абстрактном микрокомпьютере, где ram 16-битный, а rom 32-битный, и поэтому константные указатели занимают 4 байта, а неконстантные 2.

Вот что то такое я и хотел узнать.

Uter ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.