techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
1

Шаблонизированное наследование

14.12.2017, 14:47. Показов 1010. Ответов 3
Метки нет (Все метки)

Товарищи. Есть вот такой прием, позволяющий в шаблонном предке увидеть методы наследника.
Но, оно почему-то способно доставать из наследника переменные и методы... но только не типы. Попытка использовать typename B::value_type по непонятным мне причинам приводит к ошибке. Можете растолковать мне природу этого явления.

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
//g++ 5.4.0 с++14
 
#include <iostream>
 
template <typename B>
struct A {
    //void foo(typename B::value_type arg) { // ошибка
    void foo(auto arg) {
        B& self = *reinterpret_cast<B*>(this);
        self.bar();
    }
};
 
template <typename T>
struct B : public A<B<T>> {
    using value_type = T;
    
    B() {
        A<B<T>>::foo(T());
    }
    
    void bar() {
        std::cout << "Hello" << std::endl;
    }
};
 
int main() {
    B<float>();
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.12.2017, 14:47
Ответы с готовыми решениями:

Заменить наследование классов на наследование интерфейсов
#include &lt;iostream&gt; #include &lt;assert.h&gt; using namespace std; int people_on_base = 100; int...

Наследование шаблоном шаблона (наследование конструктора)
Всем привет! Думаю, что эта тема хоть и касается общих вопросов программирования, но будет уместна...

Наследование интерфейса и наследование реализации
Начал читать книгу GoF и сразу же в предисловии попал в тупик. Чем отличается наследование...

Наследование С# , наследование полей
В классе есть приватное ПОЛЕ . Мне нужно использовать его в классе потомке . Можно это не сделать...

3
зомбяк
1562 / 1211 / 344
Регистрация: 14.05.2017
Сообщений: 3,925
14.12.2017, 15:53 2
Вот так всё заработает

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template < template <typename> class B, typename T>
struct A {
 
    void foo(T arg) {
        B<T>& self = *reinterpret_cast< B<T>* >(this);
        self.bar();
    }
};
 
template <typename T>
struct B : public A<B, T> {
 
    B() {
        foo(T());
    }
    
    void bar() {
        std::cout << "Hello" << std::endl;
    }
};
Правда вызвать foo с явным указанием класса
C++
1
A<B, T>::foo(T());
у меня так и не получилось. Но в виде просто foo() работает оно правильно...

Добавлено через 9 минут
Хотя... На GCC всё наоборот, нужно именно указать класс:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template < template <typename> class B, typename T>
struct A {
 
    void foo(T arg) {
        B<T>& self = *reinterpret_cast< B<T>* >(this);
        self.bar(arg);
    }
};
 
 
template <typename T>
struct B : public A<B, T> {
 
    B(const T &arg) {
        A<B, T>::foo(arg);
    }
 
    void bar(const T& arg) {
        std::cout << "Hello " << arg << std::endl;
    }
};
А то, выше - древний микрософтовский компилятор тупит.
0
Эксперт С++
8719 / 4262 / 950
Регистрация: 15.11.2014
Сообщений: 9,669
14.12.2017, 15:58 3
Лучший ответ Сообщение было отмечено Mirmik как решение

Решение

Цитата Сообщение от Mirmik Посмотреть сообщение
Можете растолковать мне природу этого явления.

когда вы инстанцируете шаблон B
компилятор должен сгенерировать на его основе конкретный класс.
он выполняет подстановку формальных параметров:
C++
1
2
template <typename T>
struct B : public A< B<T> > {
грубо говоря возникает замена:

C++
1
struct B<float> : public A< B<float> > {
поскольку имеет место быть наследованию,
компилятору сначала необходимо сгенерировать базовый класс.

и вот в этот момент времени наследник B<float>
ещё не успел инстанцироваться полностью.
для компилятора он пока ещё "не полный тип"

и когда он пытается инстанцировать метод базового класса:
C++
1
void foo(typename B<float>::value_type arg)
то просто не знает,
что у него там может быть внутри.
0
зомбяк
1562 / 1211 / 344
Регистрация: 14.05.2017
Сообщений: 3,925
14.12.2017, 16:18 4
Цитата Сообщение от Mirmik Посмотреть сообщение
template <typename B>
Это подразумевает, что B не является шаблонным классом.

Добавлено через 7 минут
А если передавать именно шаблонный класс, то параметр шаблона с ним передаваться не будет. Этот параметр надо передавать отдельно... Собственно как в моём коде и получилось.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.12.2017, 16:18
Помогаю со студенческими работами здесь

Наследование от IEnumerator<T>: как предотвратить наследование IEnumerator
Создаю перечислитель и наследую от IEnumerator&lt;T&gt;, а он, зараза, наследует IEnumerator (который без...

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

Наследование
как создать таблицу Е12? (картинка снизу) если так пишу то получается что моя таблица Е12...

Наследование
Не могу понять в чем ошибка. #include &lt;iostream&gt; #include &lt;string&gt; using namespace std; ...


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

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

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