Мозгоправ
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
1

Инициализация константного вектора списком инициализации

24.11.2020, 05:53. Показов 2655. Ответов 13
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Есть вот такая программка:
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
#include <iostream>
#include <vector>
 
using namespace std;
 
enum class MethodMark { kFirst = 0, kSecond };
typedef std::vector<MethodMark> MethodMarkArr;
 
static const MethodMarkArr vec = { MethodMark::kFirst, MethodMark::kSecond };
 
static const char *methodMark2str(const MethodMark v)
{
    switch (v)
    {
        case MethodMark::kFirst: return "kFirst";
        case MethodMark::kSecond: return "kSecond";
        default: return "unknown value of MethodMark";
    }
}
 
int main() {
 
    for (auto x : vec)
        cout << methodMark2str(x) << ' ';
    cout << endl;
}
Если компилю в Visual Studio 2019 с родным toolset v142 - нет вопросов.

Однако, это нужно откомпилить с toolset v110 (Visual Studio 2012). Получаю ошибку:
Код
1>------ Build started: Project: test-05, Configuration: Debug x64 ------
1>main.cpp
1>main.cpp(9): error C2552: 'vec' : non-aggregates cannot be initialized with initializer list
1>        'std::vector<_Ty>' : Types with a base are not aggregate
1>        with
1>        [
1>            _Ty=MethodMark
1>        ]
1>Done building project "CodeTest-05.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
На сколько я понимаю, 2012-я студия уже поддерживала C++11?

Я в общем эту проблему обошёл, но вопросы остались: всё-таки почему ошибка? и как сделать оптимально?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.11.2020, 05:53
Ответы с готовыми решениями:

Ошибка при инициализации вектора списком
В книге Страуструпа элементы вектора объявляются так vector&lt;int&gt; v = { 5 , 7 , 9 , 4 , 6 , 8 } ;В...

Инициализация константного члена класса с проверкой значения
Допустим есть класс константным членом class a{ const int i; public: a(int...

Инициализация константного статического объекта - члена класса
Здравствуйте, у меня возникла проблема с инициализацией статического объекта, который является...

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

13
Неэпический
18099 / 10685 / 2061
Регистрация: 27.09.2012
Сообщений: 26,895
Записей в блоге: 1
24.11.2020, 09:44 2
Цитата Сообщение от L0M Посмотреть сообщение
всё-таки почему ошибка?
Цитата Сообщение от L0M Посмотреть сообщение
2012-я студия уже поддерживала C++11?
Насколько я помню - нет. Разве что частично.
1
1563 / 484 / 105
Регистрация: 17.05.2015
Сообщений: 1,472
24.11.2020, 11:01 3
Цитата Сообщение от L0M Посмотреть сообщение
На сколько я понимаю, 2012-я студия уже поддерживала C++11?
В неполном объёме, и с кучей всевозможных багов.

Таблица поддержки стандартов с++

Цитата Сообщение от L0M Посмотреть сообщение
error C2552: 'vec' : non-aggregates cannot be initialized with initializer list
Технически, поддержку "uniform initialization" (MSDN) добавили в ноябрьский копилятор Visual C++ Compiler November 2012 CTP

Вооружившись ноябрьским компилятором, вы уже сможете изготавливать собственные классы с использованием этой фичи.
Однако в стандартные классы поддержку initializer_list ещё не успели завести.
Поэтому, std::vector фича попрежнему недоступна.

Итого: вам нужна минимум Visual Studio 2013.
1
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.11.2020, 14:41 4
L0M, я не совсем понял как к проблеме относится код:
C++
1
2
3
4
5
6
7
8
9
static const char *methodMark2str(const MethodMark v)
{
    switch (v)
    {
        case MethodMark::kFirst: return "kFirst";
        case MethodMark::kSecond: return "kSecond";
        default: return "unknown value of MethodMark";
    }
}
?
Так или иначе - вектор нельзя использовать как constexpr и в С++20. Тогда, чем плох такой код?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//mvc2008 :D
#include <iostream> 
#include <vector> 
using namespace std; 
enum MethodMark {kFirst, kSecond} ; 
static const vector<MethodMark> &cvec()
{
    static vector<MethodMark> stat_cvec(2);
    stat_cvec[0]=MethodMark::kFirst,
    stat_cvec[1]=MethodMark::kSecond 
    ;
    return stat_cvec;
};
static const vector<MethodMark> &cv_ref=cvec() ;
int main()
{
    cout<<cv_ref[0]<<' '<<cv_ref[1]<<endl;
    cin.get();  
    return 0;
}


Добавлено через 2 часа 34 минуты
если вектор реально не маленький можно диспетчеризовать по типу
Диспетчеризация инициализаторов дело рук самих инициализатров
слово "инициализаторов" можно заменить на "финализаторов" без потери смысла)
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
#include <iostream> 
#include <vector> 
using namespace std; 
enum MethodMark {kFirst, kSecond} ; 
static const vector<MethodMark> &cvec()
{   
    static vector<MethodMark> stat_cvec(2);
    static int is_not_init=1;
    
    if(is_not_init){    
        stat_cvec[0] = MethodMark::kFirst, stat_cvec[1]=MethodMark::kSecond     ;
        is_not_init  = 0;
    }
    return stat_cvec;
 
};
 
static const vector<MethodMark> &cv_ref=cvec() ;
 
int main()
{
    cout<<cv_ref[0]<<' '<<cv_ref[1]<<endl;
    cin.get();  
    return 0;
}
1
Мозгоправ
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
24.11.2020, 14:44  [ТС] 5
Спасибо за ответы!

Цитата Сообщение от eva2326 Посмотреть сообщение
В неполном объёме, и с кучей всевозможных багов.
Скорее всего именно тут собака порылась

Цитата Сообщение от eva2326 Посмотреть сообщение
Итого: вам нужна минимум Visual Studio 2013.
Студия-то у меня 2019-я. Но для конкретно этого проекта мне приходится устанавливать в свойствах проекта toolset v110. Почему он не имеет поддержки Visual C++ Compiler November 2012 CTP - непонятно.

Цитата Сообщение от IGPIGP Посмотреть сообщение
как к проблеме относится код
Никак. Тупо преобразование enum-констант в строки для вывода на консоль.

Цитата Сообщение от IGPIGP Посмотреть сообщение
Тогда, чем плох такой код?
Статической переменной внутри функции на которую возвращается ссылка.

Для инициализации единичной переменной - прокатит, но если нужно как-то так?
C++
1
2
3
4
5
static const MethodMarkArr vec[] = {
    { MethodMark::kFirst, MethodMark::kSecond },
    { MethodMark::kFirst, MethodMark::kSecond, MethodMark::kSecond },
    { MethodMark::kFirst, MethodMark::kSecond, MethodMark::kFirst }
};
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.11.2020, 15:03 6
Цитата Сообщение от L0M Посмотреть сообщение
Статической переменной внутри функции на которую возвращается ссылка.
Статическая переменная внутри функции ни чем не хуже чем такая же но с перламутровыми пуговицами глобальная.
Цитата Сообщение от L0M Посмотреть сообщение
Для инициализации единичной переменной - прокатит, но если нужно как-то так?
Я добавил вариант, где присвоение происходит единожды. Хотите почленно, хотите, - еще как-то. Можно итераторы на статический массив в std::copy передать. Если зарезервировать размер сразу, то без бекинсёртинга будет быстрее. Но памяти больше (ещё и массив нужен). Не суть. Можно сделать как-то.
И в последнем примере - уже 2D вектор или это у меня двоится?

Добавлено через 9 минут
А - понял - массив векторов... И это делается также. Сначала объявляете массив из 3 а потом присваиваете. В той же функции. Иначе придётся работать с указателями на векторы или с обёртками ссылок reference_wrapper<T>, так как С++ не поддерживает неконстантных ссылок.
0
1563 / 484 / 105
Регистрация: 17.05.2015
Сообщений: 1,472
24.11.2020, 15:17 7
Цитата Сообщение от L0M Посмотреть сообщение
Почему он не имеет поддержки Visual C++ Compiler November 2012 CTP - непонятно.
Думаете, поддержка сама как то должна по волшебству появиться?

Попробуйте сначала пройти по ссылке, которую я оставила специально для вас.
Скачать и установить компилятор.
0
Мозгоправ
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
24.11.2020, 16:07  [ТС] 8
Цитата Сообщение от eva2326 Посмотреть сообщение
Думаете, поддержка сама как то должна по волшебству появиться?
Вообще-то, я как-то рассчитывал, что в Visual Studio 2019 должны присутствовать все патчи для предыдущих версий. Наверное я слишком много хочу от Microsoft?

Ну да ладно, ok. По ссылке вашей я сходил. Всё вроде здорово, однако
2.From the ‘General’ tab, change ‘Platform toolset’ from ‘Visual Studio 2012 (v110)’ to ‘Microsoft Visual C++ Compiler Nov 2012 CTP (v120_CTP_Nov)
Ну не могу я от v110 уйти
Так что качать не имеет смысла.
0
Неэпический
18099 / 10685 / 2061
Регистрация: 27.09.2012
Сообщений: 26,895
Записей в блоге: 1
24.11.2020, 16:14 9
Лучший ответ Сообщение было отмечено L0M как решение

Решение

C++
1
2
static const int arr = { MethodMark::kFirst, MethodMark::kSecond };
static const MethodMarkArr vec(arr, arr + sizeof(arr) / sizeof(*arr));
Добавлено через 3 минуты
И, к слову, зачем вообще понадобился статический константный вектор?
Почему не std::array, например?
2
Мозгоправ
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
24.11.2020, 16:39  [ТС] 10
Цитата Сообщение от IGPIGP Посмотреть сообщение
И это делается также.
Да не, понятно, что делается. Выглядит только по-уродски. (Это не к вам, а к реализации C++11 в VS2012).

Я думал, может есть более элегантное решение для такой инициализации.

Добавлено через 24 минуты
Цитата Сообщение от Croessmah Посмотреть сообщение
И, к слову, зачем вообще понадобился статический константный вектор?
Я показал пример кода, в котором возникает ошибка.

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

Поэтому табличку пришлось оформить тупо как массив массивов с инициализацией (привет, C). И написать функцию сравнения вектора с массивом.

Мне показалось логичным сравнивать вектор с вектором. Но в 2012 не прокатило.
0
Неэпический
18099 / 10685 / 2061
Регистрация: 27.09.2012
Сообщений: 26,895
Записей в блоге: 1
24.11.2020, 16:47 11
C++
1
2
3
4
5
6
7
8
//Как вариант
template<class T>
std::vector<T> initializeVector(std::initializer_list<T> initList) {
    return std::vector<T>(initList.begin(), initList.end());
}
 
//...
auto vec = initializeVector({1, 4, 7});
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.11.2020, 17:01 12
Цитата Сообщение от L0M Посмотреть сообщение
Да не, понятно, что делается. Выглядит только по-уродски. (Это не к вам, а к реализации C++11 в VS2012).
Но статический константный вектор иначе не может выглядеть. И это не к вектору. L0M, этот тип данных создан с диаметрально противоположными намерениями. И
Цитата Сообщение от L0M Посмотреть сообщение
есть вектор, в который в процессе выполнения некоей операции добавляются значения из перечисления. А потом содержимое этого вектора сравнивается с известрой строкой из таблички (ага, тот самый константный массив векторов) возможных результатов. Ну и по совпадению определяется правильно ли выполнена операция.
В константный вектор не надо пробовать что-то добавить. Ему даже присвоить нельзя:
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <vector>
using namespace std;
 
int main() {
const vector<int> cvec(3);
cvec[0]=0;//...\main.cpp|16372|error: assignment of read-only location 'cvec.std::vector<_Tp, _Alloc>::operator[]<int, std::allocator<int> >(0u)'|
 
return 0;
}
0
Мозгоправ
1745 / 1039 / 468
Регистрация: 01.10.2018
Сообщений: 2,138
Записей в блоге: 2
24.11.2020, 19:25  [ТС] 13
Цитата Сообщение от IGPIGP Посмотреть сообщение
В константный вектор не надо пробовать что-то добавить. Ему даже присвоить нельзя
Вы не поняли. Добавляю значения я в неконстантный вектор. А вот сравниваю потом этот вектор с константным, который и не получалось инициализировать.
0
Комп_Оратор)
Эксперт по математике/физике
8950 / 4704 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
24.11.2020, 20:44 14
Цитата Сообщение от L0M Посмотреть сообщение
Вы не поняли. Добавляю значения я в неконстантный вектор. А вот сравниваю потом этот вектор с константным, который и не получалось инициализировать.
Теперь понял. Да у него есть перегруженный == (а начиная с С++20 и ещё куча всего). Ну и создайте:
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
#include <iostream> 
#include <vector> 
using namespace std; 
enum MethodMark {kFirst, kSecond} ; 
static const vector<vector<MethodMark>> &cvec()
{   
    
    static int is_not_init=3;//количество в строке по совместительству) 
    static vector<vector<MethodMark>> stat_cvec(2);
    if(is_not_init){
    stat_cvec[0].resize(is_not_init), stat_cvec[1].resize(is_not_init) ;
        stat_cvec[0][0] = MethodMark::kFirst, stat_cvec[0][1]= MethodMark::kSecond, stat_cvec[0][2]=MethodMark::kSecond     ;
        stat_cvec[1][0] = MethodMark::kSecond,stat_cvec[1][1]= MethodMark::kFirst,  stat_cvec[1][2]=MethodMark::kSecond     ;
        is_not_init  = 0;
    }
    return stat_cvec;
 
};
 
static const vector<vector<MethodMark>> &cv_ref=cvec() ;
 
int main()
{
    for(size_t i=0; i<cv_ref.size(); ++i)
    {
        for(size_t j=0; j<cv_ref[i].size(); ++j)
        {
            cout<<cv_ref[i][j]<<' ';
        }
        cout<<'\n';
    }
 
    cin.get();  
    return 0;
}
1
24.11.2020, 20:44
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.11.2020, 20:44
Помогаю со студенческими работами здесь

Инициализация (ООП, списки инициализации)
Доброго времени суток, хотелось бы узнать, как происходит процесс инициализации полей класса при...

Инициализация не агрегированных данных списка инициализации не допускается
Подскажите как исправить эту ошибку #include &quot;stdafx.h&quot; #include &quot;iostream&quot; using namespace...

Инициализация в теле конструктора или в списке инициализации.
Здрасте. class random1 { public: random(): a(5) {} private: int a; };

Инициализация константного массива из элементов кортежа
Как правильно создать константный массив из элементов кортежа? (я пробовал создать не константный)...

Конструктор со списком инициализации членов
1) Какой смысл применять синтаксис конструктора со списком инициализации членов class A{...

Инициализация полей объекта в заголовочном файле против списка инициализации
Говорят, что делать так не хорошо //.h class Foo { int intField = 5; public: ...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru