LINUX.ORG.RU

Группа разработчиков Scala получила грант Евросоюза

 , , ,


1

4

Группа разработчиков языка Scala получила грант Евросоюза, выиграв конкурс языков для параллельного программирования. Разработчики получат в течение следующих 5 лет на развитие своего детища 2,3млн €.

Scala — язык программирования для платформы JVM, сочетающий возможности объектно-ориентированного и функционального программирования. Scala был разработан в лаборатории швейцарского ВУЗ’а EFPL.

>>> Подробности

★★★★★

Проверено: maxcom ()
Последнее исправление: Zhbert (всего исправлений: 3)
Ответ на: комментарий от anonymous

Очень понравилось как вы уделали scala при реализации поиска схемы аутентификации

У меня не было информации о том, что из себя представляет auth_config. Вполне возможно, что в Java на месте bla-bla-bla было бы простое обращение к Hashtable.

eao197 ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

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

1. Сокрытие технических деталей, которые не важны на данном логическом уровне. Если сейчас мы принимаем решение проводить аутентификацию или же выдавать ошибку, то не нужно сразу же показывать как именно будет выдаваться ошибка.

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

> Сокрытие технических деталей, которые не важны на данном логическом уровне. Если сейчас мы принимаем решение проводить аутентификацию или же выдавать ошибку, то не нужно сразу же показывать как именно будет выдаваться ошибка.

а по-моему ровно этим занимается функция respond

Лично моя практика показывает, что такие однострочные функции очень быстро становятся многострочными,

вот когда станут, тогда и вынесем их в функции

альтернативно можно было бы обсудить языковую фичу «определение (в т.ч. однострочной) функции прямо на месте использования»

единственный видимый мне сейчас аргумент за 2 доп. функции в том, что *возможно* полезно было бы написать тесты, направленные именно на их тестирование напрямую, а не через код функции логин; впрочем, это достаточно сомнительно — т.к. есть тулзы для проверки покрытия кода, и лучше было бы гонять в тестах целую функцию логина

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от eao197

>Может объясните, что не позволило вам вынести обработку результата AccountsStorage.find в отдельный метод, а обработку Some(user) в еще один?

То что ты совсем не понял что тут написано? :)

Все было бы ничего, если бы вы нормальный код продемострировали бы.


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

r ★★★★★
()
Ответ на: комментарий от eao197

еще как вариант если бы в скале было слово where, то вполне возможно получилось бы прилично, типа

.....
where
  doOldStyleLogin = {
    if( user.passwordMatches(password) ) 
      setupSuccessfulAuthResult(request, user) 
    else 
      respond(UNAUTHORIZED, "Authentication failed") 
  }
  doModernStyleLogin = { 
    AccessStorage.access.auth_configs.find(_.key == user.authScheme) match { 
      case None => respond(FORBIDDEN, "Unknown authentication scheme: " + user.authScheme) 
      case Some(scheme) => 
        log.debug("authenticating with " + scheme.command) 
        val exec = Runtime.getRuntime.exec(scheme.command.replace("{login}", login).replace("{password}", password)) 
        if( exec.waitFor == 0 ) 
          setupSuccessfulAuthResult(request, user) 
        else 
          respond(UNAUTHORIZED, "Authentication within " + scheme.key + " failed") 
    } 
  }
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от eao197

>Для ФП он вообще не идиоматичен, т.к. весь построен на использовании сайд-эффектов.

С дуба рухнул?

r ★★★★★
()
Ответ на: комментарий от eao197

Наверное, для провоцирования спагетти-эффекта.

Спагетти - это большой объем переходов - который ты хочешь сделать.

Незачем городить там эту функцию.

Впрочем, если не лень читать, то вот.

Жесть:

   private void setupSuccessfulAuthResult()
   {
      request.session("user") = user;
   } 

Да просто жесть.

new KnownUserLoginHandler(request, login, password, user)).handle()

Да просто жесть. Ты лучше никому такого не показывай.

У меня там нет сайд эффектов обработаны все инварианты - ты породил код с огромным количеством сайдэффектов и кучей потенциальных NPE.

Спагетти-код назван так, потому что ход выполнения программы похож на миску спагетти, то есть извилистый и запутанный. Иногда называется «кенгуру-код» (kangaroo code) из-за множества инструкций jump.

Твой код и есть спагетти - там на каждый чих идет jump - вызов подпрограммы.

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>и *гораздо* более важное — интересно, а компилятор скалы жалуется на недостижимой код в последнем «case _» ?

Ну вообще-то он достижим:) По причине раздельной компиляции - ничто не мешает мне объявить еще один case class.

А с гвардами вообще никакой компилятор не посчитает достижимость на сегодняшний день.

В данном случае просто забыл убрать из старого кода.

r ★★★★★
()
Ответ на: комментарий от eao197

>Сокрытие технических деталей, которые не важны на данном логическом уровне.

Каким это образом ты их сокрыл?

2. Лично моя практика показывает, что такие однострочные функции очень быстро становятся многострочными, когда приходится доводить код до реальной эксплуатации, в которой ошибки могут возникать в самых неподходящих местах.


А лично моя практика показывает что код с однострочниками не имеющими четкой модели абстракции быстро превразаяется в говно которое надо переписывать глобально - ибо изменить сорок восем вызовов однострочников с кучей сайдэффектов на что-то другое затруднительно.

Да и пользователи системы могут выдавать самые невероятные пожелания.


Вот именно. И пожеланий их ты не знаешь и предположения твоих однострочников неверны.

r ★★★★★
()
Ответ на: комментарий от eao197

Знаешь, мне совершенно не нравится твой код. Я и сам люблю писать длинные паттерн-матчинги с большим количеством гардов и всегда предпочитаю локальные функции отдельным методам. А количество методов стараюсь всегда минимизировать. Так получается лаконичнее, декларативнее и понятнее на мой частный взгляд. И мне кажется, что Ф.П. провоцирует писать код именно в таком стиле.

dave ★★★★★
()
Ответ на: комментарий от eao197

вот что ты скажешь про такой вариант на гипотетической скале? (при желании можешь добавить в where еще парочку однострочных функций)

@rest.Method(httpMethod = Array(POST))
def login(
    request: rest.Request,
    @rest.Param(name = "login") login: String,
    @rest.Param(name = "password") password: String
  ) = {
  debug("accessing login... " + login)

  if( login == null || password == null )
    respond(UNAUTHORIZED, "You should provide login and password")
  else
    AccountsStorage.find(login) match {
      case None => respond(UNAUTHORIZED, "User not found")
      case Some(user) => match { /// так вроде нельзя в скале? 
        case if user.inactive => respond(UNAUTHORIZED, "Account is inactive")
        case if user.authScheme == "PETRIVKA" => doOldStyleLogin
        case _ => doModernStyleLogin
      }
    }
    where /// будет полезен
      doOldStyleLogin = {
        if( user.passwordMatches(password) )
          setupSuccessfulAuthResult(request, user)
        else
          respond(UNAUTHORIZED, "Authentication failed")
      }
      doModernStyleLogin = {
        AccessStorage.access.auth_configs.find(_.key == user.authScheme) match {
          case None => respond(FORBIDDEN, "Unknown authentication scheme: " + user.authScheme)
          case Some(scheme) =>
            log.debug("authenticating with " + scheme.command)
            val exec = Runtime.getRuntime.exec(scheme.command.replace("{login}", login, "{password}", password))
            if( exec.waitFor == 0 )
              setupSuccessfulAuthResult(request, user)
            else
              respond(UNAUTHORIZED, "Authentication within " + scheme.key + " failed")
          }
      }
}
www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

> Да - мне его очень не хватает:)

одерского надо справедливо попинать за излишний академизм что ли, ключевые параметры сделал недавно, слово where до сих пор нет

ну вот смотри тогда выше — там еще одна вроде невозможная вещь сделана

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

>Ну вообще-то он достижим:) По причине раздельной компиляции - ничто не мешает мне объявить еще один case class.

не верю

заголовоки (или че там вместо этого) у скалы включаются, и видно, что щас это недостижимый код

А с гвардами вообще никакой компилятор не посчитает достижимость на сегодняшний день.

что просто означет, что все компиляторы сегодня — говно

В данном случае просто забыл убрать из старого кода.

я про то же самое

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

>Ну вообще-то он достижим:) По причине раздельной компиляции - ничто не мешает мне объявить еще один case class.

не верю, т.к. кейс классы делались специально для того, чтобы в точке использования можно было во время компиляции сказать, сколько их и каких; иначе достаточно обычных классов

на с++ есть способ сделать из обычного кейс класс :-)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от eao197

Вот тебе к стати статистика:

                 Мой/Scala        Твой/Scala       Твой/Java
LOC                 24               62               93
Монитор          да(80x25)        почти(20")        нет(20")
Jumps/Спгти         0                 8                9
SideEffects        нет               да                да
FuncLOC            17                25                24
FuncLOC%           71%               40%               25%
NJFunLOC           71%               27%               16%

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

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

Вот тебе объективные метрики.

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>не верю

Ну как не веришь.

1 января.

Option.scala:

trait Option
case class None extends Option
case class Some extends Option

Use.scala
x:Option match {
case Some
Case None
}

компиляция => либа.jar

1 января.

либа.jar

MyOpt.scala:
case class MyOpt extends Option

Результат:

MatchError в рантайме.

Раздельная компиляция же.



r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

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

Не только. У них происходит генерация специфичных методов(unapply) которыё производят матчинг и на них наложены доп ограничения, чтобы это было возможно.

r ★★★★★
()
Ответ на: комментарий от r

> Результат: MatchError в рантайме.

охренеть!!! че, правда что ли??? не поверю пока не увижу полный пример

я был об одерском лучшего мнения

все эти unapply это синтаксически свистелки, хотя и безусловно нужные

а вот семантически — в стиле ФП — необходимо ограничить кейс классы, чтобы в точке использования можно было во время компиляции сказать, сколько их и каких

я это могу сделать на плюсах *при* раздельной компиляции (используя предварительное объявление кейс-классов)

а в скале есть какой-то паттерн для этого?

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> одерского надо справедливо попинать за излишний академизм что ли, ключевые параметры сделал недавно, слово where до сих пор нет

Ололо! Для where язык должен быть ленивым.

dave ★★★★★
()
Ответ на: комментарий от r

короче: можно ли в скале сделать такой класс Option, чтобы его было невозможно расширить? (естественно, переписывание файла с исходным кодом самого класса запрещено)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от dave

> Ололо! Для where язык должен быть ленивым.

бред

where может чисто синтаксически переносится и ставится перед точкой — первым использованием объявленных там функций или переменных, и выдавать ошибку на любое использование того, что было определено после той точки

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>я был об одерском лучшего мнения

При чем тут одерский? Приложение под джаву _раздельно компилится_. Это фундаментальная фича - иначе бы требовалась компиляция из исходников всегда для того что ты хочешь.

r ★★★★★
()
Ответ на: комментарий от eao197

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

anonymous
()
Ответ на: комментарий от www_linux_org_ru

>все эти unapply это синтаксически свистелки, хотя и безусловно нужные

Это механизм реализации паттерн матчинга вообще на _любых_ объектах, а не только на аглебраических типах и примитивах.

а вот семантически — в стиле ФП — необходимо ограничить кейс классы


Это невозможно стделать в схеме раздельной компиляции. Потому что третьего января я изменю расширю исходный Optoin.scala третим вариантом, а все 48 сторонних библиотек которым компилятор сказал что матчинг эксхаустив упадут с MatchError.

я это могу сделать на плюсах *при* раздельной компиляции (используя предварительное объявление кейс-классов)


Да как? Если ты изменишь набор конструкторов в исходном файле - то скомпилированные вчера либы работать не будут.

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> where может чисто синтаксически переносится и ставится перед точкой — первым использованием объявленных там функций или переменных, и выдавать ошибку на любое использование того, что было определено после той точки

А вот уже действительно бред языкостроения. Ничего не понял.

dave ★★★★★
()
Ответ на: комментарий от r

Вот тебе к стати статистика:

Не соблаговолит ли милостивый сударь объяснить, откуда у меня в коде появились сайд-эффекты, если в вашем их не было?

eao197 ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

короче: можно ли в скале сделать такой класс Option, чтобы его было невозможно расширить?

можно. модификатор sealed. И тогда он ругнется. В моем случае не ругается потому что есть гуарды.

scala> def f(x: Option[Int]) = x  match {
     |   case Some(y) => y
     | }
<console>:8: warning: match is not exhaustive!
missing combination           None
r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

вот что ты скажешь про такой вариант на гипотетической скале?

Немногим лучше. И причины те же самые. Логика принятия решений смешана с низкоуровневыми деталями. Например — обращения к respond требуют передачи параметров. Поэтому текст изобилует символьными константами. Генерация параметров для exec, опять же. Поиск схемы аутентификации и пр.

Критерий простой — если я глядя на функцию понимаю всю ее логическую структуру, значит меня устраивает. Если же это сложно из-за деталей вызова respond, exec, find и пр., значит код следующего логического уровня нужно оттуда убирать.

eao197 ★★★★★
()
Ответ на: комментарий от dave

Я и сам люблю писать длинные паттерн-матчинги с большим количеством гардов и всегда предпочитаю локальные функции отдельным методам. А количество методов стараюсь всегда минимизировать. Так получается лаконичнее, декларативнее и понятнее на мой частный взгляд. И мне кажется, что Ф.П. провоцирует писать код именно в таком стиле.

Сюда добавить еще стремление функциональщиков давать односимвольные названия сущностям, а так же давать имена операторам из произвольного сочетания символов пунктуации и становится понятно, почему ФП так долго идет в широкие массы.

eao197 ★★★★★
()
Ответ на: комментарий от r

Этот код нормальный - просто ты не понимаешь что тут написано.

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Не соблаговолит ли милостивый сударь объяснить, откуда у меня в коде появились сайд-эффекты, если в вашем их не было?

А тот мегакласс который ты породил с состоянием 4х переменных и кучей методов относительно которых это состояние - глобально?

new KnownUserLoginHandler(requ, "x", "y", user{ authSceme="PETRIVKA"}).handleUsualAuthSchemeLogin()

Валидный вызов? Еще как. А знаешь что ты сделал? Передал чужой системе внутренний логин и пароль пользователя.

new KnownUserLoginHandler(requ, "x", "y", user).handleUsualAuthSchemeLogin().setupSuccessfulAuthResult

Валидный вызов? Еще как. Только тут ты залогинил опльзователя вообще без всяких проверок.

val h = new KnownUserLoginHandler()
h.handleInactiveUserLogin 
h.setupSuccessfulAuthResult

Вообще феерический звездец.

Глядя на handleInactiveUserLogin вообще нельзя понять что это за метод и чего это юзер - инактив.

Это API и реализиций твоего мегакласса. Так что рекомендую твой код сопроводить мегадокументацией которую надо прочитать пользователю твоего API или тебе самому чтобы потом не намудрить с вызовами твоих однострочников так чтобы долго вылавливать баги инвариантов и неверного поведения в принципе. Или навигать туда проверок инвариантности, что setup нельзя вызывать пока не прошел успешный логин, что обозначает еще больше глобальных переменных и сайд эффектов и исключаний. В каждом логине - проверку того что это таки нужный логин, а иначе исключение о том что такой метод при заданных параметрах вызывать нельзя - что обозначает еще больше кода, и еще больше сайд эффектов.

И даже с точки зрения OOP - твой клас - это ужас. Вся логика управления состоянием этого хендлера - вынесена во внешний код и размазана по куче методов. Глядя на этот класс вообще нельзя понять как им пользоваться и с чего это вызывать такие методы как handleInactiveUserLogin.

ТАк что монстра ты родил на пять балов. Ямы и прочие питфолы на каждом шагу. А если весь большой проект так выглядит - то это феерический ужас.

r ★★★★★
()
Ответ на: комментарий от eao197

> стремление функциональщиков давать односимвольные названия сущностям

Зависит от того, насколько читателю/писателю близка математика, где однобуквенные обозначения являются нормой.

> становится понятно, почему ФП так долго идет в широкие массы.

«avoid success at all costs»

dave ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>какой смысл, кроме комментирования кода, в функциях с одноразовым использованием?

читаемость же

annulen ★★★★★
()
Ответ на: комментарий от dave

>Зависит от того, насколько читателю/писателю близка математика, где однобуквенные обозначения являются нормой.

Зависит от того насколько читателю который в школе на уроках математики и физики все отлично реал однобуквенныи обозначениями промыли мозг всякие евангелисты торгующие книжками «как сделать вашь код читабельнее». Все эти названия методов вида handleInavtiveUserLogin - оттуда и произростают.

r ★★★★★
()
Ответ на: комментарий от annulen

>читаемость же

Я думаю любой читатель рещультата на жабе - тут почвесится когда его попросят объяснить допустимую модель вызовов этого Handler - класса.

r ★★★★★
()
Ответ на: комментарий от eao197

К стати еще одна метрика - если в программе куче методов называется do..., handle..., process..., execute... - значит что-то сильно не так с кодом - это сильный codeSmell обозначающий то что автор не знает как назвать функцию и называет ее абстрактно «обработай».

r ★★★★★
()
Ответ на: комментарий от dave

> А вот уже действительно бред языкостроения. Ничего не понял.

включи мозги и попробуй понять еще раз

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

Я длинные названия терпеть не могу :)

dave ★★★★★
()
Ответ на: комментарий от r

> Это невозможно стделать в схеме раздельной компиляции. Потому что третьего января я изменю расширю исходный Optoin.scala третим вариантом, а все 48 сторонних библиотек которым компилятор сказал что матчинг эксхаустив упадут с MatchError.

а давай мы еще проще сделаем — поменяем исходный код Optoin.scala и везде, где синтаксис позволяет, расставим throw MatchError ?

напомню — речь шла о неизменном Optiоn.scala

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

> можно. модификатор sealed. И тогда он ругнется. В моем случае не ругается потому что есть гуарды.

значит — говнокомпилятор

то, что задача выдать предупреждение при любых гвардах неразрешима, еще не значит, что не надо пытаться выдать предупреждение при данных конкретных гвардах — надо попытаться и выдать (в данном случае)

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

> Это механизм реализации паттерн матчинга вообще на _любых_ объектах, а не только на аглебраических типах и примитивах.

про что я и говорю — ценность у него есть, но небольшая, как у всего генеративного; а вот у связанного с верификацией sealed есть ценность, правда подорванная тем, что компилятор забывает про него при гвардах

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> можно. модификатор sealed

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

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от r

А тот мегакласс который ты породил с состоянием 4х переменных и кучей методов относительно которых это состояние - глобально?

Конечно нет. Этот экземпляр будет убираться GC сразу после завершения doLogin.

Валидный вызов? Еще как. А знаешь что ты сделал? Передал чужой системе внутренний логин и пароль пользователя.

Какой чужой системе? Класс KnownUserLoginHandler будет приватным для класса, в котором живет метод login. И публичным у него будет только метод handle. То, что я ключевое слово private не поставил для класса/метода, это да. Но ведь я его даже не компилировал.

И даже с точки зрения OOP - твой клас - это ужас. Вся логика управления состоянием этого хендлера - вынесена во внешний код и размазана по куче методов.

У него неизменяемое состояние и все методы handle* приватные. Так что наезд мимо кассы.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

> Логика принятия решений смешана с низкоуровневыми деталями. Например — обращения к respond требуют передачи параметров. Поэтому текст изобилует символьными константами.

а у тебя типа не изобилует?

Критерий простой — если я глядя на функцию понимаю всю ее логическую структуру, значит меня устраивает. Если же это сложно из-за деталей вызова respond, exec, find и пр., значит код следующего логического уровня нужно оттуда убирать.

я понял о чем ты

твой стиль напоминает канцелярский слог, которых прокатывает в простых случаях, но невыносим в сложных

«с целью предотвращения случаев успешных террористстических актов, ...» нормальный человек сократит до «чтобы не было террактов, ...»

а вот такое смешивание уровней (и значит — полагание на умение читателя «видеть») в достаточно информационно-емких проектах (вспоминаем математику) просто необходимо, иначе просто потонешь в объяснениях в виде названий функций и их аргументов (которые, сюрприз, совпадают с названиями локальных переменных)

этак можно докатиться до того, что вместо base+offset*sizeof(T) писать calculateAddress<T>(base, offset)

хотя кто-то может отстаивать понятность последней записи, но она упускает то, что очевидно из первой — например, что реальная зависимость есть только от размера Т, а не его каких-то иных свойств; ходить смотреть определение (многострочное конечно — а как же, ведь каждый параметр должен занимать отдельную строку!) простро помрешь; в то время как любой человек в теме быстро синтезирует в голове что-то вроде «а, так это здесь считают адрес!»

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>значит — говнокомпилятор

В каком смысле? На эксхаустивнесс он ругается. В гвардах он проверить не в состоянии - потому не ругается. На данный момент вроде как никто даже не пытается если есть гварды - хотя я недавно тоже выражался в списке на тему - «понятно что гарантированно нельзя но есть же огранниченное колличество случаев когда можно».

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>оно конечно можно иметь по-отдельности кейс-классы и этот модификатор

В каком смісле поотдельности? Можно сделать набор кейс классов который sealed, а можно не делать этого ограничения - все up to library designer. К стати с классов с ограничениями можно принудительно оверрайднуть:

(x:@unchecked) match {...}

r ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

а у тебя типа не изобилует?

Во-первых, настолько сильно я чужой код рефакторить не собирался :) Во-вторых, каждый отдельный метод содержит их намного меньше :)

твой стиль напоминает канцелярский слог

Скорее, это проявляется привычка проектирования «сверху-вниз».

этак можно докатиться до того, что вместо base+offset*sizeof(T) писать calculateAddress<T>(base, offset)

Не только можно, а и нужно. Поскольку если base вдруг оказывается нечетным, а T это int/long, то при последующем чтении из этого адреса, например, на SPARC-ах, можно отхватить какой-то SIG* (уже не помню какой именно, давно дело было). А вот calculateAddress вполне может данную ситуацию обрабатывать.

eao197 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.