Следующий код работает, но я хотел бы избежать предупреждения:
предупреждение: ‘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_
в списке инициализации конструктора (без изменения его типа)?
Функция, которая генерирует 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
, но если это так, отключите предупреждение локально.
Я считаю, что вы можете игнорировать это предупреждение.
Это работает, если вы поместите пустую инициализацию для массива в конструкторе:
#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;
}
Попробуй использовать
explicit fitness(T v) : vect_{}
{
//...
}
Конструктор по умолчанию (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, чтобы знать.)
Вот еще один способ, чище ИМХО, используя Инициализаторы нестатических элементов данных 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;
}