Программа для анализа шаблонов C++

398
24 июня 2017, 12:37

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

  • Какие у него должны быть методы.
  • Какие должны быть определены функции с ним.
  • Какие поля у него должны быть.
  • и т.д.

Либо же говорит, что если подставить вместо T какие-то классы, которые определены в коде, то он скомпилируется.

Пример:

Имеется такой шаблон функции:

template<class T> 
void foo(T a)
{
    T b = a;
    boo(a, 1);
    b = a - b;
    a.foo2(b);
    b.param = a.param;
    T::foo1(b);
}

Анализируя этот код, программа говорит, что класс T должен выглядеть примерно так:

class T
{
public:
    T();
    ~T();
    T(T&);
    T operator-(T& b);
    static void foo1(T);
    void foo2(T);
    UNKNOWN_TYPE param;
}

И для него должны быть перегружены такие функции:

void boo(T, INT_TYPE);

С какими параметрами он скомпилируется:

Функция foo скомпилируется, если в качестве параметра T использовать классы: 
Class1, Class2, Class3<double>, Class3<float>.
Answer 1

Нет, это невозможно. Для решения этой проблемы вы (кроме полного парсера C++) должны решить алгоритмическую проблему останова, так как шаблоны в C++ полны по Тьюрингу. А значит, определить, скомпилируется данная подстановка или нет, равносильно тому, чтобы определить, завершится произвольный алгоритм или нет.

Вот вам небольшой [де]мотивирующий пример. Определим вспомогательный шаблон, который умеет вычислять степень числа во время компиляции:

template <unsigned int x, unsigned int n>
struct static_power
{
    enum { value = static_power<x, n - 1>::value * x };
};
template <unsigned int x>
struct static_power<x, 0>
{
    enum { value = 1 };
};

Рассмотрим теперь вот такой шаблон:

template<unsigned int x, unsigned int y, unsigned int z, unsigned int n>
struct Fermat
{
    static_assert(n > 2, "Wrong power");
    static_assert(static_power<x, n>::value + static_power<y, n>::value ==
                       static_power<z, n>::value, "Fermat proof");
};

Этот шаблон можно инстанциировать только с теми числами x, y, z, n, которые являются решением Великой теоремы Ферма.

Как вы думаете, легко ли написать программу, которая сможет автоматически доказать теорему Ферма?

Примечание. Проблема здесь не только в числовых параметрах. Шаблон можно переписать и так:

template<typename X, typename Y, typename Z, typename N>
struct Fermat
{
    static_assert(N::value > 2, "Wrong power");
    static_assert(
        static_power<X::value, N::value>::value +
        static_power<Y::value, N::value>::value ==
        static_power<Z::value, N::value>::value,
        "Fermat proof");
};

P. S.: Решить задачу простым перебором классов не получится, т. к. шаблоны приносят в программу по существу бесконечное множество классов.

Например, имея

template<typename T> struct X { /**/ };

мы определяем сразу X<void>, X<X<void>>, X<X<X<void>>> и т. д.

READ ALSO
Как скрыть чужие окна? [требует правки]

Как скрыть чужие окна? [требует правки]

Работаю с чужим окном из своей программыКак сделать так, чтобы все окна, которые открывает чужое (главное) окно сразу были скрытыми ? Сейчас...

265
Появление элементов с помощью fadeIn по очереди

Появление элементов с помощью fadeIn по очереди

Есть несколько элементов с классом testДля них я использую $('

328
Подключение шрифтов в scss через mixin

Подключение шрифтов в scss через mixin

Здравствуйте почему у меня не работает вот этот mixin в(scss) вот это mixin что я делаю не так

648