Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fill std::array in the member initialization list

The following code works but I would like to avoid the warning:

warning: 'fitness::vect_' should be initialized in the member initialization list [-Weffc++]

when it is compiled with the g++ -Weffc++ switch:

#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;
}

Should I ignore the warning? Is there a way to fill vect_ in the constructor initialization list (without changing its type)?

like image 306
manlio Avatar asked Feb 24 '14 16:02

manlio


3 Answers

I believe you can ignore this warning.

It works if you place an empty initialization for the array in the constructor:

#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;
}
like image 197
user Avatar answered Nov 10 '22 09:11

user


Try to use

explicit fitness(T v) : vect_{}
{
//...
}
like image 2
Vlad from Moscow Avatar answered Nov 10 '22 09:11

Vlad from Moscow


The default constructor (read: value initializer) should work fine in this case. As std::array is an aggregate type, its elements will be each be value-initialized, which for numeric types like double means zero-initialization, and then you can use fill.

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

You might be better off using std::vector and its fill constructor if you don't want to do essentially double the initialization, though. Then your class would become:

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;
}

You could, of course, still keep the N as a template parameter, but there's no need to do so as the length doesn't need to be known at compile-time. (On the other hand, if you stick with std::array you might be able to set up the constructor as a constexpr, though that may require some template fiddling or an auxiliary constexpr function that returns an initializer list to work right, I haven't played around enough with C++11 concepts to know.)

like image 2
JAB Avatar answered Nov 10 '22 09:11

JAB