在成员初始化列表中填充 std::array



以下代码有效,但我想避免警告:

警告:"健身::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_(不更改其类型)?

我相信

你可以忽略这个警告。

如果在构造函数中为数组放置一个空初始化,它就会起作用:

#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_{}
{
//...
}

在这种情况下,默认构造函数(读取:值初始值设定项)应该可以正常工作。由于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个概念来了解。

生成

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的实现中生成警告,但如果确实如此,请在本地禁用警告。

这是

另一种方法,恕我直言,使用 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;
}

最新更新