В C++ я пытаюсь выяснить, как можно определить размер пакета параметров для функции и, кроме того, как можно определить количество параметров определенного типа (например, целых чисел).
template<int N, int N_ints, typename... Ts>
void foo(Ts... ts){
...
}
Чтобы я мог назвать это так
foo(1,2,'3')
и это было бы то же самое, что
foo<3,2>(1,2,'3')
Я даже не смог заставить работать основную проблему, т.е.
template<int N, class... Ts>
std::array<int, N> foo(Ts... ts)
{
constexpr int n = sizeof...(ts);
std::array<int, n> out;
return out;
}
int main()
{
auto a = foo(1, 2, 3, '4', 5);
return 0;
}
терпит неудачу, потому что не может сделать вывод N
.
количество int
спереди тоже можно посчитать. Нет необходимости иметь его как свободный параметр.
Возможно, подойдет конечный возвращаемый тип, как в template<typename... Ts> auto foo(Ts... ts) -> std::array<int, sizeof...(ts)> { ... }
?
Заголовок не соответствует телу вопроса. Вы знаете размер пакета параметров.
И в зависимости от используемого вами стандарта C++, возможно, полный вывод возвращаемого типа также может сработать: template<typename... Ts> auto foo(Ts... ts) { return std::array<int, sizeof...(ts)>(); }
?
template<class... Ts> std::array<int, sizeof...(Ts)> foo(Ts... ts)
работает на всех C++ начиная с 11.
Я пытался дать ответ, но, как и другие, я не совсем понимаю, в чем путаница. Вы говорите, что не можете сделать вывод N
, но в то же время вы делаете вывод с помощью constexpr int n = sizeof...(ts);
Вы слишком усложняете задачу, добавляя степени свободы, которых на самом деле нет. Информация о размере пачки и количестве вхождений int
в пачке уже есть в пачке.
#include <iostream>
template <typename T,typename... Ts>
struct count {
static const unsigned value = (std::is_same_v<T,Ts> + ...);
};
template<typename... Ts>
void foo(Ts... ts){
std::cout << "num params : " << sizeof ...(Ts) << "\n";
std::cout << "num ints : " << count<int,Ts...>::value << "\n";
}
int main() {
foo(1,2,3.0);
}
Я не был уверен, хотите ли вы посчитать все вхождения int
в пакете или только ведущие. Я выбрал первое. Пуристы могут утверждать, что static_cast<bool>
было бы более понятно, но я думаю, что здесь можно обойтись неявным преобразованием.
Если по какой-то причине вам нужно использовать аргументы шаблона, как в вашем примере, вы все равно можете это сделать:
template<typename... Ts>
auto foo(Ts... ts){
return foo_impl<sizeof ...(Ts),count<int,Ts...>::value>(ts...);
}
Спасибо! Я все еще изучаю C++, так что это очень полезно. Я могу использовать то, что вы предложили, чтобы мой случай с std::array работал godbolt.org/z/77WvbqzPc.
(извините за спам, но я не смог отредактировать свой предыдущий комментарий). Однако я не могу заставить работать немного более сложный случай, и он выдает разные ошибки с GCC и clang! Есть идеи? gcc: godbolt.org/z/o7nW7h7qr clang: godbolt.org/z/58oddnxd1
@VarchasGopalaswamy {1,3}
не имеет типа, который можно было бы вывести. И я тоже не понимаю, чего вы хотите, чтобы произошло. Сообщение об ошибке Gccs несколько сбивает с толку, но clang вполне уместен.
Я пытаюсь посмотреть, смогу ли я эмулировать синтаксис нарезки массива FORTRAN с помощью C++. В идеале можно было бы сделать что-то вроде a(1, 2, 1:5:2)
, чтобы взять соответствующие фрагменты, но я предполагаю, что это невозможно, поскольку символ :
не является тем, что нам разрешено перегружать в любом контексте. Я надеялся, что вместо этого можно будет сделать a(1, 2, {1,5,2})
, поскольку это красиво и лаконично, но я столкнулся с этой проблемой вывода шаблонов.
Я знаю, что могу сделать a(1, 2, std::array{1,5,2})
, и, кажется, это работает (см. godbolt.org/z/ETTn8x761), но было бы здорово, если бы мне не приходилось писать std::array
везде... В любом случае, я ценю помощь, поэтому далеко, и я приму ответ
@VarchasGopalaswamy проблема, с которой вы столкнулись сейчас, совершенно не связана с вопросом здесь. Вы можете открыть дополнительный вопрос
Как вы думаете, почему вам нужен
N
в списке параметров шаблона? Я имею в виду, что вы уже знаете, что этоsizeof...(ts)
нет необходимости иметь его в списке