Search code examples
c++c++11stdarrayeffective-c++

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)?


Solution

  • A function that generates a filled_array should have its return value be elided:

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

    but that requires passing in at least the size N, if not the type 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 );
    }
    

    note that storing the return value of filled_array in an auto is not advised.

    Use:

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

    I do not know if the above code will generate a warning in the implementation of filled_array_size, but if it does, disable the warning locally.