- 1
- 2
- 3
- 4
- 5
- 6
- 7
auto mesh=mesh_loader.load("wall.x").
map([](auto m){
return m.SetPosition(0.f, 0.f, 0.f);
}).map([=](auto m){
return m.SetRotation(xr,yr,zr);
}).map(::std::bind(&Mesh::SetSize, _1, 90, 60, 90)).
map(&Mesh::RecalculateNormals);
Там во-первых ссылка, в которую пихать 0 не особо прилично (хотя и возможно).
Во-вторых во fluent интерфейсе обычно тупо *this возвращают.
Да и какие в жопу исключения и ошибки в повороте мешей и в пересчете нормалей?! Вы там на ГД совсем уже упоролись? Тараса на вас нет :)
Картинку со злым котиком и злым буратином сам нагуглишь.
Правильно - жрать кактус со статусом. Тем более прецедент в стандартной либе уже есть.
В гугле они не без основания запрещены.
По-моему здесь поднимали этот вопрос, и выяснили, что никаким путем, кроме как через UB, 0 в ссылку попасть не может.
А у нее разве можно методы вызывать через точку?
::boost::optional
m.SetPosition(0.f, 0.f, 0.f) возвращает указатель на себя?
---
Вот сама тема если что http://www.gamedev.ru/flame/forum/?id=188947
Вот не надо мне это приписывать. Порядок обратный же. А вот порядок вычисления аргументов во всем этом большом выражении без sequence point будет чуть более чем UB.
В частности допустим
>>= mesh::set_rot(xr, yr, zr)
>>= mesh::set_size(xr, yr, zr)
И допустим в set_rot и в set_size делается для первого аргумента ++xr. В этот момент UB во все поля.
В данном случае по-моему очевидно что recalculate_normals будет использовать координаты модифицированные set_rot и set_size.
да
> В данном случае по-моему очевидно что recalculate_normals будет использовать координаты модифицированные set_rot и set_size.
Хм. То есть когда мы модифицируем меш, то в каком порядке вызовется операции set_rot и set_size мы не знаем и эти операции должны быть ассоциативные? Тут надо попросить Романа написать свою ::roman::optional с оператором >>=. А то как то без реализации не удаётся ответить на этот вопрос. Да и вообще пойду ка я спать.
Посмотри на ассоциативность оператора >>= и ты поймёшь, почему такой подход не сработает.
mesh::set_pos, mesh::set_rot - да, в хер знает каком порядке выполнятся (но т.к. они еще не трогали меш, и у них нет побочных эффектов - всем пофиг). А дальше все операторы << отработают в правильном порядке слева направо (и вызовут функции, которые им вернули mesh::set_pos и т.п.?).
Да, выше я ерунду сказал. Даже этот порядок не известен.
Ну тут из минусов методы mesh::* не должны иметь постэффектов вне меша в том числе и через параметры, тк перестановка местами порядка вызовов и на счет постэффектов в параметрах - UB.
> mesh::set_pos
А это типа статический метод класса mesh, возвращающий лямбду от аргумента типа mesh?
> из минусов методы mesh::* не должны иметь постэффектов вне меша
Честно говоря, мне сложно представить ситуацию, где они действительно нужны. Если ты пихаешь инкремент и потоковый вывод в одно сложное выражение, то лучше тебе сразу убиться об стену, уменьшив энтропию вселенной.
> А это типа статический метод класса mesh
или вложенная структура с 3-мя полями, для которой перегружен оператор вывода
я бы в данном случае не стал выпендриваться флюент интерфейсами, они как-то не очень сочетаются с семантикой объектов. KISS: IMHO, идеально
Так тут не потоковый вывод, а другая конструкция. Ну и как я говорил xr=xr+1 может быть внутри метода set_rot и set_size например
xr соответственно принимается по ссылке. А это между прочем вполне логичный способ для взаимодействия между методами, вызванные в этой псевдоманаде.
> m.set_pos(.0,.0,.0);
ну а допустим исключения все же запрещены. Не все же работают вне гугла
ну ты же понимаешь, что в таком случае кто-то должен написать if. Либо пользователь api, либо автор.
Если стоит задача избавить клиента библиотеки от постоянных проверок, можно соорудить что-то вроде этого
я разве спорю... меня спросили, я ответил.
> от которой воротил нос ЛиспГовно
Ну волшебства ни бывает. Разделяйте "грязный" код и "чистый", пусть ошибка будет невозможной :)
Вот на этом примере она точно невозможна. Там чистейшая математика, в которой ломаться вообще нечему (кроме load'а).
В модели попался треугольник нулевой площади (если мы строим нормали по координатам вершин) или нормали изначально были нулевой длины (если мы считаем на основе нормалей из модели)?
Легко. Часто нужны вырожденные треугольники чтобы используя Triangle Strips
http://msdn.microsoft.com/en-us/library/windows/desktop/bb206274(v=vs.85).aspx
начать рисовать новую полоску треугольников, не связанную со старыми
ПС. set_size после set_rotation - плохой порядок, не интуитивный. Как правило нам интересны размеры до поворота, а не после.
А можно пример и почему код выше плох при имлицит параллелизме?
позиционировать
повернуть
растянуть
то мы выбираем не самую удачную стратегию: мы могли бы выполнить этот алгоритм в два шага:
{ позиционировать, растянуть }
повернуть
или
повернуть
{ позиционировать, растянуть }
А выбрали делать в три шага.
>> C++
В крестах имплисит параллелизм бывает разве что в виде SIMD в циклах у умных компиляторов. Если хочется выполнять что-то КакПараллельно, нужно в любом случае существенно переписывать код.
Выполнять эти методы параллельно я особого смысла не вижу, скорее имеет смысл производить какие-то трансформации на разных участках матрицы параллельно, для этого нужно совсем всё переписать.
Если речь идёт о потенциально опасном переупорядочивании вызовов методов на некоторых архитектурах, тот тут между вызовами есть зависимость по данным - деструктивные вызовы методов mesh, так что компилятор не должен позволять менять порядок их выполнения.
> ПС. set_size после set_rotation - плохой порядок
вопросы к топик стартеру