заполните std :: array в списке инициализации члена

Следующий код работает, но я хотел бы избежать предупреждения:

предупреждение: ‘fitness :: vect_’ должен быть инициализирован в
список инициализации членов [-Weffc ++]

когда он скомпилирован с g++ -Weffc++ переключатель:

#include <array>

template<class T, unsigned N>
class fitness
{
public:
explicit fitness(T v)
{
static_assert(N, "fitness zero length");

vect_.fill(v);
}

private:
std::array<T, N> vect_;
};

int main()
{
fitness<double, 4> f(-1000.0);

return 0;
}

Должен ли я игнорировать предупреждение? Есть ли способ заполнить vect_ в списке инициализации конструктора (без изменения его типа)?

11

Решение

Функция, которая генерирует filled_array должно быть возвращено его возвращаемое значение:

template<unsigned N, typename T>
std::array<T, N> filled_array_sized( T const& t ) {
std::array<T, N> retval;
retval.fill( t );
return retval;
}

но это требует передачи по крайней мере, размер Nесли не тип T,

template<typename T>
struct array_filler {
T && t;
template<typename U, unsigned N>
operator std::array<U, N>()&& {
return filled_array_sized<N, U>( std::forward<T>(t) );
}
array_filler( T&& in ):t(std::forward<T>(in)) {}
};
template<typename T>
array_filler< T >
filled_array( T&& t ) {
return array_filler<T>( t );
}

обратите внимание, что хранение возвращаемого значения filled_array в auto не рекомендуется.

Использование:

#include <array>

template<class T, unsigned N>
class fitness
{
public:
explicit fitness(T v): vect_( filled_array( std::move(v) ) ) {
//...
}
//...

Я не знаю, будет ли приведенный выше код генерировать предупреждение при реализации filled_array_size, но если это так, отключите предупреждение локально.

1

Другие решения

Я считаю, что вы можете игнорировать это предупреждение.

Это работает, если вы поместите пустую инициализацию для массива в конструкторе:

#include <array>

template<class T, unsigned N>
class fitness
{
public:
explicit fitness(T v):
vect_{}
{
static_assert(N, "fitness zero length");

vect_.fill(v);
}

private:
std::array<T, N> vect_;
};

int main()
{
fitness<double, 4> f(-1000.0);

return 0;
}
4

Попробуй использовать

explicit fitness(T v) : vect_{}
{
//...
}
2

Конструктор по умолчанию (read: value initializer) должен нормально работать в этом случае. Как std::array является агрегатным типом, каждый его элемент будет инициализирован значением, что для числовых типов, таких как double означает нулевую инициализацию, а затем вы можете использовать fill,

explicit fitness(T v) : vect_() // or vect_{}
{
vect_.fill(v);
}

Вы могли бы быть лучше, используя std::vector и его конструктор заполнения, если вы не хотите, по сути, удваивать инициализацию. Тогда ваш класс станет:

template<class T>
class fitness
{
public:
explicit fitness(T v, unsigned n) : vect_(n, v)

private:
std::vector<T> vect_;
};

int main()
{
fitness<double> f(-1000.0, 4);

return 0;
}

Конечно, вы могли бы сохранить N в качестве параметра шаблона, но в этом нет необходимости, поскольку длину не нужно знать во время компиляции. (С другой стороны, если вы придерживаетесь std::array Вы могли бы быть в состоянии настроить конструктор как constexpr, хотя это может потребовать некоторых шаблонов или вспомогательных constexpr функция, которая возвращает список инициализаторов для правильной работы, я не достаточно разобрался с концепциями C ++ 11, чтобы знать.)

2

Вот еще один способ, чище ИМХО, используя Инициализаторы нестатических элементов данных C ++ 11:

#include <array>

template<class T, unsigned N>
class fitness
{
public:
explicit fitness(T v)
{
static_assert(N, "fitness zero length");

vect_.fill(v);
}

private:
std::array<T, N> vect_ { };
};

int main()
{
fitness<double, 4> f(-1000.0);

return 0;
}
1
По вопросам рекламы [email protected]