Некоторая путаница в отношении момента создания аргумента по умолчанию, используемого шаблоном функции - PullRequest
0 голосов
/ 14 марта 2020

Для понимания этих вопросов, пожалуйста, убедитесь, что знаете знания о метапрограммировании с сохранением состояния, тогда мы go.
Приведем цитаты о точке создания аргументов по умолчанию
[temp.point ] / 2

Если шаблон функции или функция-член шаблона класса вызывается способом, который использует определение аргумента по умолчанию для этого шаблона функции или функции-члена, точка создание аргумента по умолчанию является точкой создания шаблона функции или специализации функции-члена.

Если я правильно понимаю о приведенной выше цитате, это означает, что POI аргумента по умолчанию такой же, как POI шаблона функции, который использует аргумент по умолчанию (или, если я неправильно понимаю этот пункт, пожалуйста, поправьте меня).
Теперь готовы рассмотреть приведенные ниже коды:

#include <iostream>
template<int N>
struct state {
    friend auto call(state<N>);
};
template<int N>
struct add_state {
    friend auto call(state<N>) {
        return N;
    }
    static const int value = N;
};
template<typename T, int N>
T show(int = add_state<N>::value) {
    return T{};
}

int main() {
    show<int, 0>();
    call(state<0>{});
}

На самом деле приведенный выше код корректен (результат здесь godbolt ). Однако, по в приведенной выше цитате POI add_state<0> будет таким же, как и у show<int, 0>(), POI show<int, 0>() либо после function main, либо в конце единицы перевода (возможно, большинство компиляторов принимают конец перевода единица в качестве POI для шаблона функции), однако в этот момент вызов call(state<0>{}); не может найти определение call(state<0>{}), поэтому он будет некорректным.
результат приведенного выше кода доказал, что POI add_state<0> должен предшествовать вызову call(state<0>{}), только в этой ситуации можно найти определение call(state<0>{}). Так что меня смущает, Как интерпретировать этот вопрос, я ценю за правильные интерпретации.

1 Ответ

0 голосов
/ 23 марта 2020

Если вам нужно увидеть, где создается экземпляр вашего шаблона, используйте отладочную разборку enter image description here Похоже, что он создается вне основной функции enter image description here Код в VisualStudio непротиворечивый с кодом в godbolt , скомпилированным с gcc enter image description here

Хорошо, то есть при компиляции в режиме отладки. В режиме релиза он ведет себя по-другому, встроенный код заменяется или оптимизируется, чтобы не создавать никакого кода, если функция ничего не делает. Если вы объявите show с __declspe c (noinline), то шаблон будет выглядеть как экземпляр вне главной функции. Другими словами, это выглядит очень похоже на явную реализацию вне основной функции:

using namespace std;
template<int N> struct state {
    friend auto call(state<N>);
};
template<int N> struct add_state {
    friend auto call(state<N>) {
        return N;
    }
    static const int value = N;
};
template struct add_state<0>; //<-- instantiated here
int main()
{
    call(state<0>{});
    return 0;
}
...