Информация об изменениях

Сообщение Re[18]: Стадия компиляции от 07.01.2017 14:18

Изменено 07.01.2017 14:20 vdimas

Re[18]: Стадия компиляции
Здравствуйте, Qbit86, Вы писали:

Q>Стадия компиляции не выявит ошибку даже в пользовательском коде, если у пользователя есть свой метод `baz()`, вызова которого из библиотечного кода он не ожидает. Ведь он ожидает, что согласно документации будет вызываться `bar()`.


Ошибки перегрузки ловятся тестами, а не компилятором, ваш КО.
Такая же ошибка могла быть и не в шаблонном коде, если у целевого Т есть некий baz, помимо bar. Без тестирования ф-ии foo эти рассуждения ни о чем.


V>>Более того, в С++ легко проверить наличие нужного метода/методов даже в декларативном стиле уже имеющимися ср-вами языка (т.е. ср-в языка достаточно для разработки библиотечных приблуд требуемой функциональности).

Q>Это ты не мне расскажи, а Страуструпу. А то он не в курсе, что концепты не нужны: http://www.stroustrup.com/good_concepts.pdf

1. Я не против любых будущих улучшений языка С++, которые не будут нарушать его строгость и последовательность.
2. Речь шла о том, что многое можно делать уже сейчас.
3. Концепт не спасёт от ошибки перегрузки в твоём примере насчет bar/baz.

Последнее утверждение раскрывать требуется?


V>>В общем, когда речь идёт о реализации параметрического полиморфизма в C# vs C++ — то тут что-либо обсуждать сложно, т.к. у этих языков явно разные весовые категории в плане такого полиморфизма.

Q>Да, выражать констрейнты номинативно через типы — не лучший подход. Конечно, шаблоны в C++ мощнее (в этом же смысле генерация через T4 ещё «мощнее»). Но они непроверяемые. Вот код на C#, аналогичный приведённому выше плюсовому:
Q>
interface IBarable
Q>{
Q>    void Bar();
Q>}
Q>...
Q>static void Foo<T>(T t) where T: IBarable
Q>{
Q>    t.Baz(); // Ошибка: Имелось в виду `t.Bar()`. Ловится компилятором автора библиотеки.
Q>}
Q>


При наличии IBarable.Baz не ловится.

Ну и, в том же дотнете гораздо чаще случаются ошибки, когда вызывается не та сигнатура Bar, что ожидал разработчик. Тут только тесты помогут, повторюсь, которые должны проверить все ветки кода.


Q>Тут ошибка не только будет сразу подчёркнута в IDE, но ещё и по точке intellisense выдаст список допустимых ограничениями методов. Могут ли такое в C++ упомянутые «имеющиеся ср-ва языка в декларативном стиле, с полтыка найденные на этом сайте»?


В С++ intellisense уж точно не предложит никакого baz. ))

Ну и, опять повторюсь, что ограничения в стиле C# организовать можно:
using namespace std;

#define where(A, Predicate, B)     static_assert(Predicate<A, B>::value, "Predicate "#A" "#Predicate" "#B" is not satisfied")

template<typename T>
struct A {
    void foo() {}
};

template<typename T>
struct B {
    where(A<T>, is_base_of, T);

    void bar(T * t) { t->foo(); } // ok
};

struct C : A<C> {};
struct D {};

B<C> bc; // ok
B<D> bd; // error C2338: Predicate A<T> is_base_of T is not satisfied


Можно и помощнее ограничения задавать, ес-но, см. <type_traits>.
Re[18]: Стадия компиляции
Здравствуйте, Qbit86, Вы писали:

Q>Стадия компиляции не выявит ошибку даже в пользовательском коде, если у пользователя есть свой метод `baz()`, вызова которого из библиотечного кода он не ожидает. Ведь он ожидает, что согласно документации будет вызываться `bar()`.


Ошибки перегрузки ловятся тестами, а не компилятором, ваш КО.
Такая же ошибка могла быть и не в шаблонном коде, если у целевого Т есть некий baz, помимо bar. Без тестирования ф-ии foo эти рассуждения ни о чем.


V>>Более того, в С++ легко проверить наличие нужного метода/методов даже в декларативном стиле уже имеющимися ср-вами языка (т.е. ср-в языка достаточно для разработки библиотечных приблуд требуемой функциональности).

Q>Это ты не мне расскажи, а Страуструпу. А то он не в курсе, что концепты не нужны: http://www.stroustrup.com/good_concepts.pdf

1. Я не против любых будущих улучшений языка С++, которые не будут нарушать его строгость и последовательность.
2. Речь шла о том, что многое можно делать уже сейчас.
3. Концепт не спасёт от ошибки перегрузки в твоём примере насчет bar/baz.

Последнее утверждение раскрывать требуется?


V>>В общем, когда речь идёт о реализации параметрического полиморфизма в C# vs C++ — то тут что-либо обсуждать сложно, т.к. у этих языков явно разные весовые категории в плане такого полиморфизма.

Q>Да, выражать констрейнты номинативно через типы — не лучший подход. Конечно, шаблоны в C++ мощнее (в этом же смысле генерация через T4 ещё «мощнее»). Но они непроверяемые. Вот код на C#, аналогичный приведённому выше плюсовому:
Q>
interface IBarable
Q>{
Q>    void Bar();
Q>}
Q>...
Q>static void Foo<T>(T t) where T: IBarable
Q>{
Q>    t.Baz(); // Ошибка: Имелось в виду `t.Bar()`. Ловится компилятором автора библиотеки.
Q>}
Q>


При наличии IBarable.Baz не ловится.

Ну и, в том же дотнете гораздо чаще случаются ошибки, когда вызывается не та сигнатура Bar, что ожидал разработчик. Тут только тесты помогут, повторюсь, которые должны проверить все ветки кода.


Q>Тут ошибка не только будет сразу подчёркнута в IDE, но ещё и по точке intellisense выдаст список допустимых ограничениями методов. Могут ли такое в C++ упомянутые «имеющиеся ср-ва языка в декларативном стиле, с полтыка найденные на этом сайте»?


В С++ intellisense уж точно не предложит никакого baz. ))

Ну и, опять повторюсь, что ограничения в стиле C# организовать можно:
using namespace std;

#define where(A, Predicate, B) \
    static_assert(Predicate<A, B>::value, "Predicate "#A" "#Predicate" "#B" is not satisfied")

template<typename T>
struct A {
    void foo() {}
};

template<typename T>
struct B {
    where(A<T>, is_base_of, T);

    void bar(T * t) { t->foo(); } // ok
};

struct C : A<C> {};
struct D {};

B<C> bc; // ok
B<D> bd; // error C2338: Predicate A<T> is_base_of T is not satisfied


Можно и помощнее ограничения задавать, ес-но, см. <type_traits>.
Или можно на основе is_base_of сделать предикат is_derived_from, поменяв аргументы-типы местами (для дотнетчиков так привычней).