Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++
Войти
Регистрация
Восстановить пароль
 
hoggy
Заблокирован
Эксперт С++
1

Как проинициализировать std::stack<const int> obj ( std::stack<int>{} );

31.03.2017, 14:40. Просмотров 356. Ответов 10
Метки нет (Все метки)

добрый день.

вопрос в коде:

http://rextester.com/VCVVML6656

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <stack>
 
//-std=c++14 -fopenmp -O2 -g3 -pedantic -Wall -Weffc++ -Wextra 
//-Woverloaded-virtual -Wctor-dtor-privacy -Wnon-virtual-dtor 
//-Wold-style-cast -Wconversion -Wsign-conversion -Winit-self 
//-Wunreachable-code
 
template<class T> struct item
{
    item(const T& v):val(v){}
    T val;
};
 
int main() 
{
    using  item_t = item<int>;
    using citem_t = item<const int>;
    
    using  stack_t = std::stack< item_t>;
    using cstack_t = std::stack<citem_t>;
    
    
    stack_t st;
    for(int n=0; n<10; ++n)
        st.push(n);
    
    // как проинициализировать "константную" 
    // версию стека от неконстантного?
    cstack_t cst(st); 
}
ну то есть понятно, что stack_t и cstack_t - два принципиально разных типа,
которые друг о друге ничего не знают.

ну как быть теперь в такой ситуации?

то есть, конечно можно std::stack - за борт,
и поюзать std::deque напрямки.
но интересно решение именно для std::stack

Добавлено через 35 минут
придумал вот такой костыль (вроде даже работает)
http://rextester.com/YNR17465

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <stack>
 
//-std=c++14 -fopenmp -O2 -g3 -pedantic -Wall -Weffc++ -Wextra 
//-Woverloaded-virtual -Wctor-dtor-privacy -Wnon-virtual-dtor 
//-Wold-style-cast -Wconversion -Wsign-conversion -Winit-self 
//-Wunreachable-code
 
template<class T> struct item
{
    operator const T&()const { return val; }
    
    item(const T& v):val(v){}
    T val;
};
 
int main() 
{
    using  item_t = item<int>;
    using citem_t = item<const int>;
    
    using  stack_t = std::stack< item_t>;
    using cstack_t = std::stack<citem_t>;
    
    stack_t st;
    for(int n=0; n<10; ++n)
        st.push(n);
    
    // расчет на то, что строение объекта у "константной" 
    // и "не константной" версии одинаковое
    cstack_t cst;   
    new(&cst) stack_t(st);
    
    while(!cst.empty())
    {
        std::cout << cst.top()<<std::endl;
        cst.pop();
    }
}
вот интересно...
насколько это потенциально опасное решение?
вы бы пропустили такое через ревью?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.03.2017, 14:40
Ответы с готовыми решениями:

std::string, std::fstream, ошибка кучи
где то начало вылетать при операции += с локальной переменной std::string....

В чем разница между long int и short int
Извините если вопрос нубский, но я ни как не могу понять смысл long int и short...

Ошибка: invalid types ‘int[int]’ for array subscript
Всем доброго дня, после компиляции выводится ошибка, которая меня вводит в...

std::filesystem && std::asio и пр
Пытался найти хоть какие-то сроки включения всего этого в стандарт (так же...

stack overflow in C++
#include&lt;iostream&gt; #include&lt;cmath&gt; using namespace std; int main() { int...

10
Kastaneda
Jesus loves me
Эксперт С++
4949 / 3026 / 346
Регистрация: 12.12.2009
Сообщений: 7,627
Записей в блоге: 2
Завершенные тесты: 1
31.03.2017, 16:28 2
Думаю честным путем это никак не сделать, т.к.
Цитата Сообщение от hoggy Посмотреть сообщение
что stack_t и cstack_t - два принципиально разных типа,
которые друг о друге ничего не знают.
У меня еще вот так на rextester.com собралось (правда с варнингами)
C++
1
cstack_t cst(*reinterpret_cast<cstack_t*>(&st));
А мой g++ 4.9.3 ругается на
C++
1
std::cout << cst.top()<<std::endl;
Bash
1
2
3
4
5
6
7
8
tmp.cpp: In function ‘int main()’:
tmp.cpp:34:30: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
         std::cout << cst.top() << std::endl;
                              ^
In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4/iostream:39:0,
                 from tmp.cpp:1:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4/ostream:602:5: note: initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = item<const int>]’
     operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
Возможно компилятор с ума сходит, top() для не константного объекта возвращает reference, что есть const int& а нашем случае и, возможно, он не понимает как не константное может быть константным)
Цитата Сообщение от hoggy Посмотреть сообщение
вы бы пропустили такое через ревью?
Хз как оно еще может "стрельнуть", в любом случае оба решения попахивают, я бы не пропустил.

Добавлено через 2 минуты

Не по теме:

У меня как-то реджектнули код с placement new на ревью, т.к. placement new выглядит страшно и такой синтаксис мало кто знает.

0
hoggy
Заблокирован
Эксперт С++
31.03.2017, 17:05  [ТС] 3
Цитата Сообщение от Kastaneda Посмотреть сообщение
Хз как оно еще может "стрельнуть"
сейчас это работает лишь по одной причине:
строения объектов совпадают.

только это никто как бе не гарантируется.

Цитата Сообщение от Kastaneda Посмотреть сообщение
А мой g++ 4.9.3 ругается на
как нибудь можно было бы это на онлайн-компиляторе проверить?
0
Kastaneda
Jesus loves me
Эксперт С++
4949 / 3026 / 346
Регистрация: 12.12.2009
Сообщений: 7,627
Записей в блоге: 2
Завершенные тесты: 1
31.03.2017, 18:27 4
Попробовал дома тоже на 4.9.3, но на Kubuntu, все нормально. На работе Gentoo, странно, не думаю, что поведение компилятора отличается в разных дистрибутивах Linux.
0
avgoor
1042 / 610 / 157
Регистрация: 05.12.2015
Сообщений: 1,735
31.03.2017, 18:30 5
Цитата Сообщение от hoggy Посмотреть сообщение
сейчас это работает лишь по одной причине:
строения объектов совпадают.
Можно определить оператор каста/конструктор в структуре item (как в прошлой теме).
Затем у микрософта в стеке определен _Get_container(). Просто создаем deque<citem_t> копированием из st._Get_container(). И конструируем cstack_t перемещением этого дека.

В gcc, т.к. в стеке контейнер по стандарту протектед, можно применить для доступа к контейнеру паттерн Паблик Морозов.
0
hoggy
Заблокирован
Эксперт С++
31.03.2017, 20:16  [ТС] 6
Цитата Сообщение от avgoor Посмотреть сообщение
Можно определить оператор каста/конструктор в структуре item (как в прошлой теме).
не поможет.

Цитата Сообщение от avgoor Посмотреть сообщение
у микрософта в стеке определен _Get_container()
не портируемо.

Цитата Сообщение от avgoor Посмотреть сообщение
Паблик Морозов
это точно никакое ревью не пройдет

я решил просто уходить со стека на какой нибудь вектор.
0
avgoor
1042 / 610 / 157
Регистрация: 05.12.2015
Сообщений: 1,735
31.03.2017, 22:13 7
Цитата Сообщение от hoggy Посмотреть сообщение
я решил просто уходить со стека на какой нибудь вектор
А почему не на дек, оберткой которого стек и является?
0
hoggy
Заблокирован
Эксперт С++
31.03.2017, 23:17  [ТС] 8
Цитата Сообщение от avgoor Посмотреть сообщение
А почему не на дек, оберткой которого стек и является?
дек наверна оверкилл, для стека
0
avgoor
1042 / 610 / 157
Регистрация: 05.12.2015
Сообщений: 1,735
31.03.2017, 23:21 9
Цитата Сообщение от hoggy Посмотреть сообщение
дек наверна оверкилл, для стека
Комитет считает иначе, ибо в стандарте стэк определен как:
C++
1
2
3
namespace std {
template <class T, class Container = deque<T> >
class stack {
Мне вообще непонятно, почему дек так редко используют.
0
hoggy
Заблокирован
Эксперт С++
31.03.2017, 23:37  [ТС] 10
Цитата Сообщение от avgoor Посмотреть сообщение
Комитет считает иначе, ибо в стандарте стэк определен как:
ну и какой профит от дека при вставке в задницу?
и взятия с задницы?
1
avgoor
1042 / 610 / 157
Регистрация: 05.12.2015
Сообщений: 1,735
31.03.2017, 23:43 11
hoggy, Профит в том, что память там выделяется порциями по мере надобности и при выделении ничего никуда не копируется, как при использовании вектора. А что он двусторонний - так отличия от односторонней реализации - минимальные (лишняя операция сложения).
2
31.03.2017, 23:43
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.03.2017, 23:43

C++ STL Создать контейнер (Stack)
1. Создать объект-контейнер и заполнить его данными, тип stack 2. Просмотреть...

Stack smashing detected + Массивы + Random
Здравствуйте. Пытаюсь реализовать программу, которая выполняла бы несколько...

Run-Time Check Failure #2 - Stack around the variable 'A' was corrupted
#include &lt;iostream&gt; #include &lt;iomanip&gt; using namespace std; int main() {...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru