Может ли кто-нибудь объяснить мне правила порядка разрешения шаблонов? - PullRequest
2 голосов
/ 01 мая 2011

Хорошо, полный псевдокод здесь.

template <typename T>
void fun(/*...*/)
{
    some_meta_typelist pushback T;
}

Таким образом, идея заключается в том, что в любой момент, когда создается эта функция, она выращивает объект some_meta_typelist. Если это сделано через границы, есть ли гарантия, что все вызовы этого механизма построения шаблона будут скомпилированы до того, как список типов будет использован, возможно, в функции MPL :: fold. Когда они оцениваются и когда вы можете быть уверены, что они выполнены? Должно ли это быть ограничено модулями компиляции и никогда не выходить за пределы .cpp? Есть ли эквивалент вызова функции со статической переменной, чтобы убедиться, что объект был создан перед использованием?

Обновление

Я смотрю на идею, что объекты, вызывающие систему, будут затем создавать список типов, который необходим системе для ее работы. Мне кажется, что список типов будет полностью зависеть от порядка компиляции и поэтому не будет правильным подходом, кроме одного файла CPP. Я знаю, что MSVC компилируется в алфавитном порядке, или, по крайней мере, раньше, поэтому я мог назвать конечный файл ZZZZ.cpp, под финальным я подразумеваю тот, который нуждается в полностью построенном списке типов. Это не безопасное или совместимое решение. Это тот случай? и есть ли работа вокруг?

Спасибо всем

1 Ответ

3 голосов
/ 01 мая 2011

Вот упрощенная, упрощенная версия работы экземпляра шаблона (я рассмотрю документацию Boost для fold ).

Скажем, вы - компилятор C ++ (давайте назовем вас clang ... это довольно крутое имя) и вы с удовольствием читаете файл .cpp для его компиляции.Вы видите все эти нормальные функции, такие как void foo(), float magic(int x, double p) и int main(int argc, char** argv).Затем вы сталкиваетесь с чем-то вроде этого:

template <typename T>
struct is_fun
{
    typedef some_other_type<T> something_else;
    typedef typename something_else::value value;
}

Здесь clang говорит: Круто, я знаю об этой структуре с именем is_fun, которая является шаблоном с одним типом в качестве параметра.На данный момент is_fun является неинициализированным шаблоном.Важно отметить, что здесь ничего не компилируется.Когда clang видит шаблонное что-либо, он проверяет синтаксис (в той степени, в которой он способен) и движется дальше.Не существует способа создать неинициализированный шаблон в объектном коде - он является чисто C ++ и не скомпилирован.

Позже он приходит и видит, как is_fun используется в таком выражении:

typedef vector<long,float,short,double,float,long,long double> types;
typedef fold<
             types,
             int_<0>,
             if_< is_fun<_2>,next<_1>,_1 >
            >
        ::type number_of_fun;

Теперь clang ленив и просто говорит: «Хорошо, number_of_fun - это просто псевдоним для этой отвратительной вещи».Еще раз, это не делает ничего.Позже в вашем коде он видит это:

int foo()
{
    const int fun = number_of_fun::value;
    return fun;
}

Теперь , он что-то сделал с шаблоном number_of_fun.Теперь параметры шаблона будут заполнены значениями (потому что для этого требуется number_of_fun::value).clang будет проходить через все элементы Boost и, в конце концов, закончится вашим шаблонным is_fun.Первое, что ему нужно в списке, это long (это то, что делает свертывание вектора), поэтому он создает новый тип на основе long со всеми заполненными T:

struct is_fun<long>
{
    typedef some_other_type<long> something_else;
    static const int value = typename something_else::value;
}

Этот тип будет скомпилирован, потому что он был использован.Основное правило шаблонов C ++: когда вы используете его во время компиляции, он будет создан, что означает, что он будет скомпилирован.Во время выполнения не нужно делать ничего особенного.

...