Что такое угловые скобки для значений аргументов и для чего они используются?

Я привык к угловым скобкам, используемым для указания типа, в качестве параметра:

vector<int> vecOfInts ;

а в rapidjson есть такой код:

document.Parse<0>(json) ;

на document.Parse подпись метода:

template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
    RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
    GenericStringStream<Encoding> s(str);
    return ParseStream<parseFlags>(s);
}

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

что здесь делает код, и почему он передает стоимостью в угловые скобки?

это хорошая идея? Когда?

1 ответов


здесь происходит два разных фактора.

во-первых, можно определить шаблоны, которые параметризованы над вещами, отличными от просто типов. Например, вот простой тип массива:

template <typename T, size_t N> struct Array {
    T arr[N];
};

мы можем использовать это как

Array<int, 137> myArray;

известно, что vector<int> и vector<double> различные типы. Но теперь мы должны также отметить, что Array<int,137> и Array<int,136> различные типы.

во-вторых, при использовании шаблонов, компилятор должен быть в состоянии выяснить значение для всех аргументов шаблона. При использовании классов шаблонов обычно указываются все аргументы шаблона. Ты не говоришь vector x, например, но вместо этого скажите что-то вроде vector<double> x. При использовании функций шаблона большую часть времени компилятор может вычислять аргументы. Например, использовать std::sort, вы просто говорите что-то вроде

std::sort(v.begin(), v.end());

тем не менее, вы также можете написать

std::sort<vector<int>::iterator>(v.begin(), v.end());

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

template <unsigned parseFlags>
GenericDocument& Parse(const Ch* str) {
    RAPIDJSON_ASSERT(!(parseFlags & kParseInsituFlag));
    GenericStringStream<Encoding> s(str);
    return ParseStream<parseFlags>(s);
}

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

Parse<0>(myString);

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

у вас могут быть методы, которые объединяют немного вывода типа и немного явных параметров типа. Например, в Boost есть функция lexical_cast который может выполнять преобразования в строковые типы и из них. Сигнатура функции для преобразования из строкового типа В тип строка

template <typename Target, typename Source>
    Target lexical_cast(const Source& arg);

здесь, Если вы называете lexical_cast, компилятор может выяснить, что Source, но он не может вывести Target без подсказок. Использовать lexical_cast, следовательно, вы напишете что-то вроде

std::string myString = boost::lexical_cast<std::string>(toConvertToString);

в более общем плане компилятор говорит, что вам нужно указать некоторое количество аргументов шаблона (необязательно 0), и он попытается вывести остальные. Если это возможно, отлично! Если нет, это ошибка времени компиляции. Используя это, если хотите, вы можете написать такую функцию, как

template <int IntArgument, typename TypeArgment>
    void DoSomething(const TypeArgument& t) {
       /* ... */
}

чтобы вызвать эту функцию, вам нужно будет вызвать он такой:

DoSomething<intArg>(otherArg);

здесь это работает, потому что вы должны явно сказать компилятору, что IntArgument есть, но тогда компилятор может вывести TypeArgument от типа аргумента до DoSomething.

надеюсь, что это помогает!