Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127

Написать шаблон ptr_cast, который работает аналогично dynamic_cast (задача из книжки Страуструпа)

26.12.2015, 19:33. Показов 1598. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Кто может написать шаблон ptr_cast, который работает аналогично dynamic_cast? Задача из Страуструпа, не могу это реализовать?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
26.12.2015, 19:33
Ответы с готовыми решениями:

dynamic_cast() шаблон
Здорова! Пытаюсь свой шаблон функции создать dynamic_cast() это ptr_cast() но ничо не получается. Не могу никак сам шаблон написать ...

Создать шаблон, который работает подобно алгоритму find
Создать шаблон, который работает подобно алгоритму find. Шаблон должен получать один параметр типа, который передает тип пары итераторов,...

Как работает dynamic_cast
Почему все if-ы срабатывают? void print(Shape *shape) { if (dynamic_cast<Point*>(shape)) { cout <<...

14
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.12.2015, 20:32
Лучший ответ Сообщение было отмечено DavidTs как решение

Решение

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <iostream>
#include <type_traits>
using namespace std;
 
//////////////////////////////////////////////////////////////////////////
 
template<class D, class B>
class IsDerivedFrom
{
private:
    class Yes
    {
        char a[1];
    };
    class No
    {
        char a[10];
    };
 
    static Yes Test( B* );
    static No Test( ... ); 
 
public:
    enum
    {
        Is = sizeof( Test( static_cast<D*>(0) ) ) == sizeof( Yes ) ? 1 : 0
    };
};
//
template<class T>
class IsDerivedFrom<T, T>
{
public:
    enum
    {
        Is = 0
    };
};
 
//////////////////////////////////////////////////////////////////////////
template <typename CastTo>
class ptr_cast
{
private:
    CastTo*                                 m_pointer;
 
public:
    template <typename CastFrom>
    ptr_cast( CastFrom expression )
    {
        static_assert(std::is_polymorphic<std::remove_pointer<CastFrom>::type>::value, "not virtual");
        static_assert(std::is_polymorphic<std::remove_pointer<CastTo>::type>::value, "not virtual");
 
 
        m_pointer = (IsDerivedFrom<std::remove_pointer<CastTo>::type, std::remove_pointer<CastFrom>::type > ::Is)
            ? (CastTo*)expression 
            : (nullptr) ;
    }
    operator CastTo*()
    {
        return m_pointer;
    }
};
 
//////////////////////////////////////////////////////////////////////////
 
 
class A
{
public:
    virtual void f()
    {
 
    }
};
class B : public A
{
public:
 
    virtual void f()
    {
    }
};
class C
{
public:
    virtual void t()
    {
 
    }
};
 
//////////////////////////////////////////////////////////////////////////
 
int main()
{
    A* ptr = new B();
  
    
    cout << ptr_cast<B>(ptr) << endl;
    cout << ptr_cast<C>(ptr) << endl;
}
0
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
26.12.2015, 20:36  [ТС]
rikimaru2013, Спасибо.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.12.2015, 20:39
Да куда спасибо - я там нагавнокодил дико - сейчас кучу текста меняю на using и убираю static_assert на SFINAE
0
26.12.2015, 20:43

Не по теме:

rikimaru2013, а если еще учесть, что Страуструп совсем не это просил сделать... то вообще :)

Write a template ptr_cast that works like dynamic_cast, except that it throws bad_cast rather than returning 0.

0
26.12.2015, 20:46

Не по теме:

DrOffset, если я всё подсумировать, то мне лучше уйти в Web-разработку. Да? :cry:

0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
26.12.2015, 20:56
Лучший ответ Сообщение было отмечено rikimaru2013 как решение

Решение

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
если я всё подсумировать, то мне лучше уйти в Web-разработку. Да?
Да ты не при чем. Просто ТС не полностью задание скинул.
Странно было бы думать, что Страуструп ждет от людей кода, подобного приведенному выше.
Задание предполагает всего-навсего вот такую простую реализацию:
C++
1
2
3
4
5
6
7
8
template <typename T, typename F>
T ptr_cast(F * p)
{
    T t = dynamic_cast<T>(p);
    if(!t)
        throw std::bad_cast();
    return t;
}
Добавлено через 2 минуты
А далее там идет вот такое задание:
Consider how dynamic_cast might be implemented. Define and implement a dcast template that behaves like dynamic_cast but relies on functions and data you define only. Make sure that you can add new classes to the system without having to change the definitions of dcast or previously-written classes.
Вот здесь он уже предлагает сочинять свою реализацию RTTI.
2
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.12.2015, 20:57
Вот
Кликните здесь для просмотра всего текста
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <iostream>
#include <type_traits>
using namespace std;
 
//////////////////////////////////////////////////////////////////////////
struct A                                    { virtual void f() {} };
struct B : public A                         { virtual void f() {} }; 
struct C                                    {};
struct D                                    { virtual void t() {} };
//////////////////////////////////////////////////////////////////////////
 
template<class D, class B>
class IsDerivedFrom
{
private:
    class Yes
    {
        char a[1];
    };
    class No
    {
        char a[10];
    };
 
    static Yes Test( B* );
    static No Test( ... );
 
public:
    enum
    {
        Is = sizeof( Test( static_cast<D*>(0) ) ) == sizeof( Yes ) ? 1 : 0
    };
};
//
template<class T>
class IsDerivedFrom<T, T>
{
public:
    enum
    {
        Is = 0
    };
};
 
//////////////////////////////////////////////////////////////////////////
template<typename T>
struct property
{
    enum
    {
        is_polymorphic = std::is_polymorphic<std::remove_pointer_t<T>>::value,
    };
};
//////////////////////////////////////////////////////////////////////////
 
template <typename CastTo, typename std::enable_if<property<CastTo>::is_polymorphic>::type* = nullptr >
class ptr_cast
{
private:
    
 
    CastTo*                                 m_pointer;
 
public:
    template <typename CastFrom>
    ptr_cast( CastFrom expression )
    {
        using FromType = std::remove_pointer_t<CastFrom>;
        using ToType = std::remove_pointer_t<CastTo>;
 
        m_pointer = (IsDerivedFrom<ToType, FromType > ::Is)
            ? (CastTo*)expression
            : (nullptr);
    }
    operator CastTo*()
    {
        return m_pointer;
    }
};
 
//////////////////////////////////////////////////////////////////////////
 
 
int main()
{
    A* ptr = new B();
 
    
    cout << ptr_cast<B>(ptr) << endl;       // Expect valid adress
    cout << ptr_cast<D>(ptr) << endl;       // Expect nullptr
    //cout << ptr_cast<C>(ptr) << endl;     // Expect compile-error
}


Почему у меня строка с ptr_cast<C>(ptr) не подчёркуется вовремя сборки intellisense visual studio 2015 ?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.12.2015, 22:40
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Вот
сама идея пофиксить максимум ошибок в компалтайме, безусловно хороша.
однако, ваш код не работает.

он не делает самого главного - не умеет фиксить ошибки времени выполнения.

http://rextester.com/YVK46581

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <iostream>
#include <cassert>
#include <type_traits>
using namespace std;
 
//////////////////////////////////////////////////////////////////////////
struct A                                    { virtual void f() {} };
struct B : public A                         { virtual void f() {} }; 
struct BB : public A                        { virtual void f() {} }; 
struct C                                    {};
struct D                                    { virtual void t() {} };
//////////////////////////////////////////////////////////////////////////
 
template<class D, class B>
class IsDerivedFrom
{
private:
    typedef char (&Yes)[1];
    typedef char (&No)[10];
 
    static Yes Test( B* );
    static No Test( ... );
 
public:
    enum
    {
        Is = sizeof( Test( static_cast<D*>(0) ) ) == sizeof( Yes ) ? 1 : 0
    };
};
//
template<class T>
class IsDerivedFrom<T, T>
{
public:
    enum
    {
        Is = 0
    };
};
 
//////////////////////////////////////////////////////////////////////////
template<typename T>
struct property
{
    enum
    {
        is_polymorphic = std::is_polymorphic< std::remove_pointer_t<T> >::value,
    };
};
//////////////////////////////////////////////////////////////////////////
 
template <typename CastTo, typename std::enable_if<property<CastTo>::is_polymorphic>::type* = nullptr >
class ptr_cast
{
private:
    
 
    CastTo*                                 m_pointer;
 
public:
    template <typename CastFrom>
    ptr_cast( CastFrom expression )
    {
        using FromType = std::remove_pointer_t<CastFrom>;
        using ToType = std::remove_pointer_t<CastTo>;
 
        m_pointer = (IsDerivedFrom<ToType, FromType > ::Is)
            ? (CastTo*)expression
            : (nullptr);
    }
    operator CastTo*()
    {
        return m_pointer;
    }
};
 
//////////////////////////////////////////////////////////////////////////
 
 
int main()
{
    A* ptr = new B();
 
    assert( ptr_cast<B>(ptr)   && "ERROR: invalid type");
    assert( !ptr_cast<D>(ptr)  && "ERROR: invalid type");
    assert( !ptr_cast<BB>(ptr) && "ERROR: invalid type");
}
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.12.2015, 22:51
hoggy, сравнил ваш и мой код через diff тулзы:

отрефакторили чучуть, добавили другой класс и assert -

следовательно код правильный и на этапе компиляции если используют неправильно будет ошибка. Другое поведение: эта попытка имитации dynamic_cast приведение или Nullptr - так где я ошибся.

Если бы как в dynamic_cast не полиморфный тип подчёркнулся - кажись я добился результата на все 100%, но не подчёркует интелесенс (потому, что много вложеностей), а так же есть compile-error.

Добавлено через 2 минуты
C++
1
2
3
IInterfacePointer* ptr = dynamic_cast<IInterfacePointer*>( pointer );
if( ptr )
ptr->hello();
Разве не в этом смысл dynamic_cast который многими кодинг-стайлами запрещен:
- так как его всегда юзают не верно - низлежащие типы зависят от вверхлежащих
- нагрузка использование RTTI в ран-тайме
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
26.12.2015, 22:55
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
кажись я добился результата на все 100%
проверь вот на таком варианте:
C++
1
2
3
4
5
6
7
8
9
10
11
class A  { public: virtual void foo() {} };
class B  { public: virtual void boo() {} };
 
class C : public A, public B {};
 
int main()
{
    A * p = new C;
    std::cout << dynamic_cast<B *>(p) << std::endl;
    std::cout << ptr_cast<B>(p) << std::endl;
}
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.12.2015, 23:12
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
отрефакторили чучуть
да, я просто хотел вам показать,
что для sfinae не нужно создавать классы Yes/No.
ссылки на массивы срабатывают абсолютно точно так же,
а буковок писать приходится всего две строчки.

Цитата Сообщение от rikimaru2013 Посмотреть сообщение
добавили другой класс и assert -
ага, и вот тест на каст с этим классом у вас проваливается.
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
так где я ошибся.
ну смотрите:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
int main()
{
    A* ptr = new B(); //<--- по факту создали бэху
 
    auto* bb =  ptr_cast<BB>(ptr); // а кастим к бэбэхе
    // такой каст не правомерный
    // и динамик_каст вернул бы nullptr
 
    // но ваша реализация кастит теплое к мягкому
    // и возвращает нелегальный адрес
 
    // должен быть nullptr, или сработает дебаг-защита
    assert( !ptr_cast<BB>(ptr) && "ERROR: invalid type");
}
1
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.12.2015, 23:28
Ну если имитировать работу RTTI определения типа, то согласно имплимитациям о которых я читал в статьях и книгах это:
- помещение в VTABLE метода getMyTypeiD() (для работы typeid() говорят так и делается)

Там же прочитал, что если если без RTTI, то и нужнос сравнить указали одного ли типа:
- сравнение первых 4 байт( (size_t*)class_ptr == (size_t*)class_ptr2)
0
Игогошка!
 Аватар для ct0r
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
26.12.2015, 23:46
rikimaru2013, еще годный материал:
http://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html
https://github.com/earl/llvm-m... /Casting.h
1
3 / 3 / 8
Регистрация: 25.11.2015
Сообщений: 127
27.12.2015, 11:14  [ТС]
DrOffset,
Цитата Сообщение от DrOffset Посмотреть сообщение
template <typename T, typename F>
T ptr_cast(F * p)
{
* * T t = dynamic_cast<T>(p);
* * if(!t)
* * * * throw std::bad_cast();
* * return t;
}
Ага, он именно этого хотел
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
27.12.2015, 11:14
Помогаю со студенческими работами здесь

Задача из книги Страуструпа (4.6.3)
Читаю книгу Страуструпа не могу понять как сортировать функцией sort. пример взят и переписан их книги: &quot;Принципы и практика...

Задача из книги Страуструпа
Нужна ваша помощь или хотя бы подсказка, в одном из упражнений в книге Страуструпа &quot; Программирование. Принципы и практика с...

Задача из книги Страуструпа
Меня настораживает несколько странная формулировка, я не понимаю зачем так предлагают решать задачу: Напишите программу, содержащую цикл...

Задача из книги Страуструпа
В общем, не могу понять логику, по которой необходимо выполнить небольшое задание. Само задание: Напишите функцию print(), которая...

Задача из книжки на while и if.else
Файл с условием прикрепил. Вопрос: в учебнике постоянно разбирались примеры с использованием классов. Мне кажется, в этой задаче ни к...


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

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru