Как я могу создать конструктор C++, который принимает переменное число int
Это возможно, чтобы ограничить тип аргументов в конструктор с переменным числом аргументов?
Я хочу иметь возможность выразить
X x1(1,3,4);
X x2(3,4,5);
// syntax error: identifier 'Args'
class X {
template<int ... Args> X(Args...)
{
}
};
// this works but allows other types than int
class Y {
template<typename ... Args> Y(Args...)
{
}
};
Изменить, чтобы прояснить намерение:
Чего я хочу добиться, так это сохранить данные, переданные в конструктор (константы, известные во время компиляции), в статический массив.
Так что есть и другие
template<int ...values>
struct Z
{
static int data[sizeof...(values)];
};
template<int ... values>
int Z<values...>::data[sizeof...(values)] = {values...};
И в конструкторе X я хотел бы использовать Z так:
class X {
template<int ... Args> X(Args...)
{
Z<Args...>::data // do stuff with data
}
};
Возможно ли это, что я должен использовать integer_sequence?
4 ответа:
Так как у вас есть следующее:
template<int... values> struct Z { static int data[ sizeof...( values ) ]; }; template <int... values> int Z<values...>::data[ sizeof...( values ) ] = { values... };
Вы можете использовать
std::integer_sequence<>
, чтобы передать ints вZ<>
:struct X { template <int... values> X( std::integer_sequence<int, values...> ) { for ( int i{ 0 }; i < sizeof...( values ); ++i ) Z<values...>::data[ i ]; // do stuff with data } };
Вы можете сделать себе вспомогательный тип, чтобы облегчить вызов ctor:
template <int... values> using int_sequence = std::integer_sequence<int, values...>;
Тогда вы можете создать экземпляр своего класса следующим образом:
int main() { X x( int_sequence<1, 3, 5>{} ); }
Вы можете использовать
std::initializer_list
:#include <iostream> #include <initializer_list> void myFunc(std::initializer_list<int> args) { for (int i: args) std::cout << i << '\n'; } int main(){ myFunc({2,3,2}); // myFunc({2,"aaa",2}); error! }
Вы обновили свой вопрос, чтобы указать, что все, что вам нужно,-это время компиляции
Но просто ради будущих читателей, которые могут прийти сюда в поисках ответа, я хотел бы также ответить на ваш первоначальный вопрос "возможно ли ограничить тип аргументов в вариадическом конструкторе?"std::integer_sequence
, что замечательно.Да. Один путь (лучший путь? Я не уверен) является SFINAE на дополнительный параметр шаблона, как это:
struct X { template< class... TT, class E = std::enable_if_t<(std::is_same_v<TT, int> && ...)> > X(TT... tt) { // do stuff with the ints "tt..." } };
&& ...
является складчатым выражением, новым в С++17. Если ваш компилятор не поддерживает fold-выражения, просто замените его на свернутый вручнуюall_of
.
Нет, вы не можете ограничить тип. Однако вы можете использовать
static_assert
. Было бы что-то вроде этого:static_assert(std::is_same<int, Args>::value ..., "have to be ints.");
Не пытались использовать расширение в
static_assert
, как это. Вам может понадобиться constexpr, который возвращает bool или что-то еще.