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

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

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

Author24 — интернет-сервис помощи студентам
Кто может написать шаблон ptr_cast, который работает аналогично dynamic_cast? Задача из Страуструпа, не могу это реализовать?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
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)) ...

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

14
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.12.2015, 20:32 2
Лучший ответ Сообщение было отмечено 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  [ТС] 3
rikimaru2013, Спасибо.
0
2549 / 1208 / 358
Регистрация: 30.11.2013
Сообщений: 3,826
26.12.2015, 20:39 4
Да куда спасибо - я там нагавнокодил дико - сейчас кучу текста меняю на using и убираю static_assert на SFINAE
0
DrOffset
26.12.2015, 20:43
  #5

Не по теме:

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

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

0
rikimaru2013
26.12.2015, 20:46
  #6

Не по теме:

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

0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
26.12.2015, 20:56 7
Лучший ответ Сообщение было отмечено 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 8
Вот
Кликните здесь для просмотра всего текста
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
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.12.2015, 22:40 9
Цитата Сообщение от 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 10
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
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
26.12.2015, 22:55 11
Цитата Сообщение от 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
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
26.12.2015, 23:12 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 13
Ну если имитировать работу RTTI определения типа, то согласно имплимитациям о которых я читал в статьях и книгах это:
- помещение в VTABLE метода getMyTypeiD() (для работы typeid() говорят так и делается)

Там же прочитал, что если если без RTTI, то и нужнос сравнить указали одного ли типа:
- сравнение первых 4 байт( (size_t*)class_ptr == (size_t*)class_ptr2)
0
Игогошка!
1801 / 708 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
26.12.2015, 23:46 14
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  [ТС] 15
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
27.12.2015, 11:14
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
27.12.2015, 11:14
Помогаю со студенческими работами здесь

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

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

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

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

Задача из Страуструпа про исключения
Пожалуйста, помогите с задачкой из книги Страуструпа: 14.12.9. (*1) Имеется int main() { /*...


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

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