Что такое угловые скобки для значений аргументов и для чего они используются?
Я привык к угловым скобкам, используемым для указания типа, в качестве параметра:
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
.
надеюсь, что это помогает!