Автор Тема: Что не может C++ на этапе компиляции.  (Прочитано 5913 раз)

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Что не может C++ на этапе компиляции.
« : Февраль 29, 2012, 03:51:22 pm »
Наткнулся в интернетах на демонстрацию немощности "обобщенки"/параметрического полиморфизма плюсов. Конкретно - оно не позволяет например решить такую задачку: есть два массива (списка, вектора - не важно) неизвестной на этапе компиляции длины. Нужно убедиться (на этапе компиляции) что они будут таки обязательно одинаковой длины. То есть что при создании (для простоты задачи, пусть длина указывается только при создании, затем изменять длину нельзя) им передали одно и то же число.

В шарпе это сделать можно, вроде как даже в жабе можно, а вот в плюсах нельзя. Позор.

Оригинальная постановка задачи (возможно более корректная чем у меня) и решение на Haskell'e тут.
Решение на C# и попытка решение на C++ тут.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #1 : Февраль 29, 2012, 03:52:53 pm »
Для нетерпеливых и самоуверенных приведу сразу решения на хаскелле и шарпе:

Haskell:
module Test where
data Nil = Nil
data Cons a = Cons Integer a
class ScalarProduct a where scalarProduct :: a -> a -> Integer
instance ScalarProduct Nil where scalarProduct Nil Nil = 0
instance ScalarProduct a => ScalarProduct (Cons a) where scalarProduct (Cons n1 a1) (Cons n2 a2) = n1 * n2 + scalarProduct a1 a2
main :: Integer -> Integer
main n = main' n 0 Nil Nil where
  main' :: ScalarProduct a => Integer -> Integer -> a -> a -> Integer
  main' 0 _ as bs = scalarProduct as bs
  main' n i as bs = main' (n-1) (i+1) (Cons (2*i+1) as) (Cons (i^2) bs)

C#:
using System;
interface ScalarProduct<A> {
  int scalarProduct(A second);
}
class Nil : ScalarProduct<Nil> {
  public Nil(){}
  public int scalarProduct(Nil second) {
    return 0;
  }
}
class Cons<A> : ScalarProduct<Cons<A>> where A : ScalarProduct<A> {
  public int value;
  public A tail;
  public Cons(int _value, A _tail) {
    value = _value;
    tail = _tail;
  }
  public int scalarProduct(Cons<A> second){
    return value * second.value + tail.scalarProduct(second.tail);
  }
}
class _Test{
  public static int main(int n){
    return _main(n, 0, new Nil(), new Nil());
  }
  public static int _main<A>(int n, int i, A first, A second) where A : ScalarProduct<A> {
    if (n == 0) {
      return first.scalarProduct(second);
    } else {
      return _main(n-1, i+1, new Cons<A>(2*i+1,first), new Cons<A>(i*i, second)); // Works
      //return _main(n-1, i+1, first, new Cons<A>(i*i, second)); // Doesn't work
    }
  }
}
public class Test{
  public static void Main(){
    Console.Write("Enter a number: ");
    int val = Convert.ToInt32(Console.ReadLine());
    Console.WriteLine(_Test.main(val));
  }
}
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #2 : Февраль 29, 2012, 04:02:08 pm »
Наткнулся в интернетах на демонстрацию немощности "обобщенки"/параметрического полиморфизма плюсов.

Казалось бы - причем тут оберон? :) Хотелось бы хотя бы одного примера практического использования подобного достижения...

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #3 : Февраль 29, 2012, 04:10:24 pm »
Наткнулся в интернетах на демонстрацию немощности "обобщенки"/параметрического полиморфизма плюсов.

Казалось бы - причем тут оберон? :) Хотелось бы хотя бы одного примера практического использования подобного достижения...
Есть некий Сергей Зефиров, у него блог весь в практических использований подобных достижений. Собственно он это все в продакшине пользует :-) Продакшн у него специфический, но тем не менее. Блог его тут: http://thesz.livejournal.com/

А вот тут его статья про всякое подобное и практическое применение оного подобного: http://fprog.ru/2010/issue5/serguey-zefirov-et-al-error-economy/

PS. Оберон тут при том, что иногда смотришь на С++ и думаешь, а не слишком ли он прост и примитивен? Любопытно посмотреть на плюсы как частенько некоторые (в том числе и я) смотрим на Оберон.

PPS. Вообще, хочется подумать, нельзя ли подобные вещи делать как-то проще и привычней нежели в том же Хаскеле, или в шарпах.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Geniepro

  • Hero Member
  • *****
  • Сообщений: 1955
  • Знайте- истина в том, что повторено трижды подряд!
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #4 : Март 01, 2012, 06:25:04 am »
В паскале было элементарно:
"array[10] of integer" и "array[10] of integer" -- один тип
"array[10] of integer" и "array[11] of integer" -- разные типы...


to iterate is human, to recurse, divine

Салат «рекурсия»: помидоры, огурцы, салат…

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #5 : Март 01, 2012, 08:36:53 am »
В паскале было элементарно:
"array[10] of integer" и "array[10] of integer" -- один тип
"array[10] of integer" и "array[11] of integer" -- разные типы...
А какое отношение это имеет к обсуждаемой проблеме?
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

Peter Almazov

  • Sr. Member
  • ****
  • Сообщений: 482
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #6 : Март 01, 2012, 09:22:10 am »
Не силен в данной теме, но если раскомментировать строку, которая "// Doesn't work", то сообщение об ошибке выглядит так:
"The type arguments for method '_Test._main<A>(int, int, A, A)' cannot be inferred from the usage. Try specifying the type arguments explicitly."
То есть речь идет о выводе типов.
Я не знаю, декларируется ли в С++ вывод типов. Кто знает, напишите.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #7 : Март 01, 2012, 02:12:58 pm »
Не силен в данной теме, но если раскомментировать строку, которая "// Doesn't work", то сообщение об ошибке выглядит так:
"The type arguments for method '_Test._main<A>(int, int, A, A)' cannot be inferred from the usage. Try specifying the type arguments explicitly."
То есть речь идет о выводе типов.
Я не знаю, декларируется ли в С++ вывод типов. Кто знает, напишите.

1. Вычисление типов в С++ есть (через одно место, но тем не менее).
2. Твой пример некорректен, потому что речь идет о неизвестной на этапе компиляции длине.

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re: Что не может C++ на этапе компиляции.
« Ответ #8 : Март 01, 2012, 02:15:49 pm »
Не силен в данной теме, но если раскомментировать строку, которая "// Doesn't work", то сообщение об ошибке выглядит так:
"The type arguments for method '_Test._main<A>(int, int, A, A)' cannot be inferred from the usage. Try specifying the type arguments explicitly."
...
2. Твой пример некорректен, потому что речь идет о неизвестной на этапе компиляции длине.
Это ж не пример, а ровно то что слуается когда в этот шарповый код попытаешься засунуть два вектора разной (но не известной на этапе компиляции) длины. То есть тут все правильно. Ошибка на этапе компиляции.
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"