Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/7: Рейтинг темы: голосов - 7, средняя оценка - 4.86
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760

[template] почему код не компилируется без конструктора

15.03.2017, 18:53. Показов 1544. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
добрый вечер.
вопрос поместил прямо в коде.

http://rextester.com/AESO94403

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <string>
#include <vector>
 
//-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
 
namespace detail {
 
    #define dFOR_CONST \
        bool is_const = std::is_const<Container>::value
 
    template<class Container, dFOR_CONST> class iterator 
    {
        using no_const = std::remove_const_t<Container>;
        
        using non_const_iterator 
            = iterator<no_const, false>;
    public:
/*        
        //--- почему без этого конструктора не компилируется?
        iterator(const non_const_iterator& rhs) 
            :v(rhs.v)    
        {}
        
        //error: conversion from ‘iterator<std::vector<int> >’ to non-scalar type ‘iterator<const std::vector<int> >’ requested
        //iterator<const vec> it2 = it1;
*/
        
        iterator(const iterator&){}
        iterator(){}
    private:
        int v = 10;
    };
    
    template<class Container> class iterator<Container, false>
            : public iterator<const Container>
    {
        using parent = iterator<const Container>;
    public:
        using parent::parent;
    };
    
    #undef dFOR_CONST
    
}//namespace detail 
 
template<class Container>
class iterator: public detail::iterator<Container>
{
    using parent
        = detail::iterator<Container>;
public:
    using parent::parent;
};
 
int main() 
{
    using vec = std::vector<int>;
    iterator<vec> it1;
    iterator<const vec> it2 = it1;
    (void) it2;
}
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.03.2017, 18:53
Ответы с готовыми решениями:

Почему не компилируется код
Доброго времени суток, я только начал постигать азы великого и могучего, по этому не смейтесь если вам вопрос покажется слишком простым......

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

Visual Studio выдаёт ошибку при вынесении объявления функции с template в .h файл. Без template всё работает
Проект содержит три файла: Source.cpp, arrTreat.h, arrTreat.cpp. Source.cpp: #include &lt;iostream&gt; using std::cout; using...

5
Эксперт С++
1675 / 1047 / 174
Регистрация: 27.09.2009
Сообщений: 1,945
15.03.2017, 19:36
Но это же очевидно. A и const A - не один и тот же тип, поэтому если B - шаблон класса, то B<A> и B<const A> - уже совсем разные типы, независимые друг от друга и друг с другом не связанные. Приведение из одного в другой придётся писать явно. А лучше подсуетиться снаружи и снимать const с параметра шаблона.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
15.03.2017, 23:14  [ТС]
Цитата Сообщение от Nick Alte Посмотреть сообщение
Но это же очевидно
не константная версия:

class iterator: public detail::iterator<Container>

в итоге унаследуется от:

C++
1
2
template<class Container> class iterator<Container, false>
            : public iterator<const Container>
который по итогу унаследуется от:
template<class Container, dFOR_CONST> class iterator

поэтому, очевидно, что не константная версия - наследник от константной.

почему не срабатывает неявное приведение к предку?
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
16.03.2017, 03:52
hoggy, В принципе, Nick Alte, все правильно сказал. Это detail::iterator<vec> и detail::iterator<const vec> находятся в одной иерархии. А вот ::iterator<vec> и ::iterator<const vec> - нет.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.03.2017, 12:36  [ТС]
Цитата Сообщение от avgoor Посмотреть сообщение
В принципе, Nick Alte, все правильно сказал
нет, не правильно.

Цитата Сообщение от avgoor Посмотреть сообщение
Это detail::iterator<vec> и detail::iterator<const vec> находятся в одной иерархии. А вот ::iterator<vec> и ::iterator<const vec> - нет.

::iterator<vec> унаследован от detail::iterator<const vec>
::iterator<const vec> унаследован от detail::iterator<const vec>

detail::iterator<const vec>
имеет конструктор копии.

при запуске функции,
которая принимает ссылку на базовый классс,
прямой наследник должен быть неявно к нему приведен.

поэтому, ::iterator<vec> должен был быть приведен к detail::iterator<const vec>

следующий код иллюстрирует это положение:

http://rextester.com/YKFOX52726
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <string>
#include <vector>
 
//-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
 
namespace detail {
 
    #define dFOR_CONST \
        bool is_const = std::is_const<Container>::value
 
    template<class Container, dFOR_CONST> class iterator 
    {
        using no_const = std::remove_const_t<Container>;
        
        using non_const_iterator 
            = iterator<no_const, false>;
    public:
        //--- почему без этого конструктора не компилируется?
        iterator(const non_const_iterator& rhs) 
            :v(rhs.v)    
        {}
        
        //error: conversion from ‘iterator<std::vector<int> >’ to non-scalar type ‘iterator<const std::vector<int> >’ requested
        //iterator<const vec> it2 = it1;
        
        iterator(const iterator&){}
        iterator(){}
    private:
        int v = 10;
    };
    
    template<class Container> class iterator<Container, false>
            : public iterator<const Container>
    {
        using parent = iterator<const Container>;
    public:
        using parent::parent;
    };
    
    #undef dFOR_CONST
    
}//namespace detail 
 
template<class Container>
class iterator: public detail::iterator<Container>
{
    using parent
        = detail::iterator<Container>;
public:
    using parent::parent;
};
 
template<class Container>
void example_cast(detail::iterator<const Container>&)
{
    std::cout 
        << "cast from ::iterator<non-const-type> to detail::iterator<const-type>"
        << std::endl;
}
 
int main() 
{
    using vec = std::vector<int>;
    iterator<vec> it1;
    iterator<const vec> it2 = it1;
    
    example_cast(it1);
}
кроме того, особенное внимание обратите на конструктор:

C++
1
2
3
iterator(const non_const_iterator& rhs) 
            :v(rhs.v)    
        {}
здесь iterator - предок non_const_iterator
и non_const_iterator неявно кастится к iterator

если бы iterator и non_const_iterator не были бы связанны прямыми родственными узами,
мы бы получили ошибку компиляции:
iterator не имел бы права залезть в приватные данные non_const_iterator

однако, non_const_iterator успешно кастится к iterator,
а iterator доступны приватные данные других iterator


так что вопрос остается в силе:
зачем был нужен явный конструктор,
если оно итак может и должно кастиццо к предку?
0
 Аватар для avgoor
1550 / 877 / 179
Регистрация: 05.12.2015
Сообщений: 2,555
16.03.2017, 17:06
Лучший ответ Сообщение было отмечено hoggy как решение

Решение

Цитата Сообщение от hoggy Посмотреть сообщение
зачем был нужен явный конструктор,
если оно итак может и должно кастиццо к предку?
В каком месте оно должно каститься?
Вот ваш код, упрощенный до предела:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class B;
 
class A {
public:
    A(const B&) {} // это конструктор, без которого не работает
    A() {}
};
 
class B : public A {};
 
class C : public A {
public:
    using A::A; //строка *
};
 
class D : public B {};
 
int main()
{
    D d;
    C c = d;
}
При наследовании конструктора в строке "*", конструктор A(const A&) превратится в C(const C&), как сказано в святом писании стандарте 12.9. Поэтому нужен A(const B&) который унаследуется в C без изменений. Ответ остается тем же. Классы не в одной иерархии.
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.03.2017, 17:06
Помогаю со студенческими работами здесь

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

Компилируется без ошибок, но командная строка, почему то, сразу же закрывается
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;fstream&gt; #include &lt;list&gt; #include &lt;iterator&gt; int main() { ...

Как работает данный код? И почему не компилируется?
Обьясните пожалуйста как работает данный код, и скажите почему он не компилируется? И есть ли способ считать числа еще быстрее? ...

Почему указанный код не компилируется в Visual Studio?
#include &quot;pch.h&quot; #include &lt;iostream&gt; using namespace std; int j, x; main() { cin &gt;&gt; x; if (x &gt; 1) { j = x - 5; ...

Объяснить почему компилируется этот код (динамические массивы)
Что это =-O int*array = new int; То есть почему компилится? anti-k, пожалуйста, прочитайте правила форума и постарайтесь...


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

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
Загрузка PNG с альфа-каналом на SDL3 для Android: с помощью SDL3_image
8Observer8 27.01.2026
Содержание блога SDL3_image - это библиотека для загрузки и работы с изображениями. Эта пошаговая инструкция покажет, как загрузить и вывести на экран смартфона картинку с альфа-каналом, то есть с. . .
Влияние грибов на сукцессию
anaschu 26.01.2026
Бифуркационные изменения массы гриба происходят тогда, когда мы уменьшаем массу компоста в 10 раз, а скорость прироста биомассы уменьшаем в три раза. Скорость прироста биомассы может уменьшаться за. . .
Воспроизведение звукового файла с помощью SDL3_mixer при касании экрана Android
8Observer8 26.01.2026
Содержание блога SDL3_mixer - это библиотека я для воспроизведения аудио. В отличие от инструкции по добавлению текста код по проигрыванию звука уже содержится в шаблоне примера. Нужно только. . .
Установка Android SDK, NDK, JDK, CMake и т.д.
8Observer8 25.01.2026
Содержание блога Перейдите по ссылке: https:/ / developer. android. com/ studio и в самом низу страницы кликните по архиву "commandlinetools-win-xxxxxx_latest. zip" Извлеките архив и вы увидите. . .
Вывод текста со шрифтом TTF на Android с помощью библиотеки SDL3_ttf
8Observer8 25.01.2026
Содержание блога Если у вас не установлены Android SDK, NDK, JDK, и т. д. то сделайте это по следующей инструкции: Установка Android SDK, NDK, JDK, CMake и т. д. Сборка примера Скачайте. . .
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru