Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Гладко было на бумаге  (Прочитано 4867 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 08-10-2011 18:52 » 

Проблема наблюдается в компиляторах как C++, так и C#, и, возможно, других языков со статической типизацией и параметризированными классами.

Есть классы:
Код: (C++)
template<class A, class B> class Z {};
template<class C, class D> class Y {};
template<class E, class F> class X: public Z<Y<E, F>, F> {};
template<class G, class H> class W: public Y<G, H> {};
class V {};
class U {};
class T: public X<W<V, U>, U> {};

Z<W<V, U>, U> *a = new T();
Чисто логически и теоретически последняя строчка должна выполняться, поскольку T - потомок Z, несмотря на параметры. На уровне байтов памяти (в случае reinterpret_cast) совместимость будет. Однако компиляторы заявляют, что приведение типов невозможно.

Компилятор работает последовательно: сначала он подставляет параметры шаблонов, и только потом полученный код обрабатывается на предмет сочетаемости типов в силу наследования.

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

В случае перебора по аналогии с тем, как работает среда исполнения Prolog, дерево поиска выглядело бы следующим образом:
Код:
T
  :
    [
     E = W<V, U>
     F = U
    ]
    X<W<V,U>,U>
      = [
         W<V,U>
          : [
             C = G = V
             D = H = U
            ]
            Y<V,U>
        ]
        X<Y<V,U>,U>
         : [
            A = E = Y<U, V>
            B = F = U
           ]
           Z<Y<Y<V,U>,U>,U> !
         : [
            A = Y<E,F>
                 = [
                    E = V
                    F = U
                   ]
                   Y<V,U>
            B = F = U
           ]
           Z<Y<V,U>,U> !
      : [
         A = E = W<V,U>
         B = F = U
        ]
        Z<Y<W<V,U>,U>,U> !
         = [
            W<V,U>
             : [
                C = G = V
                D = H = U
               ]
               Y<V,U>
           ]
           Z<Y<Y<V,U>,U>,U> !
      : [
         A = Y<E,F>
              = [
                 E = V
                 F = U
                ]
                W<V,U>
                 : [
                    C = G = V
                    D = H = U
                   ]
                   Y<V,U>
         B = F = U
        ]
        Z<Y<V,U>,U> !
: - наследование, = - подстановка, [] - предварительные вычисления, ! - результат

Из этого следует: во-первых и главное, неопределённость результатов типизации, которая заставит компилятор хранить все варианты типов для согласования разных мест программы, каждый раз подбирая наиболее подходящее соответствие и умножая неопределённость типа в расчётных цепочках (особенно в свете новомодных деклараций с автоматической типизацией - auto и var); во-вторых, пример благополучно разрешился бы.

Но... реальность грубее и примитивнее. У компиляторов лишь один вариант приведения:  Z<Y<Y<V,U>,U>,U>. С одной стороны, это хорошо, что один, с другой стороны, это следствие упрощённых алгоритмов анализа кода с минимумом отложенных решений.
« Последнее редактирование: 08-10-2011 18:55 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Алик
Постоялец

kz
Offline Offline

« Ответ #1 : 21-10-2011 08:18 » 

Честно говоря, не очень въехал в суть проблемы... забавно было разбираться в коде примера, в подстановках и всем таком.

наверное, я ошибаюсь, но мне общая мысль поста показалась такой: жаль, что подстановка параметров шаблона происходит так, как происходит. Если бы было по-другому - конечно, присутствовала бы неоднозначность результатов, но за то компиляторы бы работали гораздо дольше...
подчеркиваю - не стремлюсь критиковать! просто, во-первых, интересно подискутировать, а во-вторых, хотел бы до конца и правильно понять мысль (которую, вероятно, понял привратно) и цель публикации этого поста
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 21-10-2011 08:46 » new

Алик, подискутировать о чём? Вроде я никаких вопросов не ставил - сплошное утверждение фактов.

Цель же поэтическая - крик души Улыбаюсь
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines