1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

std::vectorを拡張してみた(その後)

Last updated at Posted at 2017-11-25

前回の「std::vectorを拡張してみた」のその後です。
色々な指摘を受けて検討した結果、以下のようにしてみました。
エイリアスとグローバル関数を定義することで、std::vector<double>で四則演算やmean,sd,normが計算できるようにしてみました。範囲for文が直観的だったので採用。

my_vector.h
#include <vector>
#include <cmath>

using my_vector = std::vector<double>;

inline my_vector& operator+=(my_vector& lhs, const my_vector& rhs) {
    for (std::size_t i = 0; i < lhs.size(); i++)
        lhs[i] += rhs[i];
    return lhs;
}
inline my_vector& operator-=(my_vector& lhs, const my_vector& rhs) {
    for (std::size_t i = 0; i < lhs.size(); i++)
        lhs[i] -= rhs[i];
    return lhs;
}
inline my_vector& operator*=(my_vector& lhs, const my_vector& rhs) {
    for (std::size_t i = 0; i < lhs.size(); i++)
        lhs[i] *= rhs[i];
    return lhs;
}
inline my_vector& operator/=(my_vector& lhs, const my_vector& rhs) {
    for (std::size_t i = 0; i < lhs.size(); i++)
        lhs[i] /= rhs[i];
    return lhs;
}
inline my_vector& operator+=(my_vector& lhs, const double rhs) {
    for (auto& e : lhs) e += rhs;
    return lhs;
}
inline my_vector& operator-=(my_vector& lhs, const double rhs) {
    for (auto& e : lhs) e -= rhs;
    return lhs;
}
inline my_vector& operator*=(my_vector& lhs, const double rhs) {
    for (auto& e : lhs) e *= rhs;
    return lhs;
}
inline my_vector& operator/=(my_vector& lhs, const double rhs) {
    for (auto& e : lhs) e /= rhs;
    return lhs;
}

inline my_vector operator+(const my_vector& lhs, const my_vector& rhs) {
    return my_vector(lhs) += rhs;
}
inline my_vector operator-(const my_vector& lhs, const my_vector& rhs) {
    return my_vector(lhs) -= rhs;
}
inline my_vector operator*(const my_vector& lhs, const my_vector& rhs) {
    return my_vector(lhs) *= rhs;
}
inline my_vector operator/(const my_vector& lhs, const my_vector& rhs) {
    return my_vector(lhs) /= rhs;
}
inline my_vector operator+(const my_vector& lhs, const double rhs) {
    return my_vector(lhs) += rhs;
}
inline my_vector operator-(const my_vector& lhs, const double rhs) {
    return my_vector(lhs) -= rhs;
}
inline my_vector operator*(const my_vector& lhs, const double rhs) {
    return my_vector(lhs) *= rhs;
}
inline my_vector operator/(const my_vector& lhs, const double rhs) {
    return my_vector(lhs) /= rhs;
}

inline double mean(const my_vector& obj) {
    const std::size_t size = obj.size();
    if (size == 0) return 0;
    double t = 0;
    for (auto e : obj) t += e;
    return t / size;
}
inline double sd(const my_vector& obj) {
    const std::size_t size = obj.size();
    if (size < 2) return 0;
    double m = mean(obj);
    double t = 0;
    for (auto e : obj) t += (e - m) * (e - m);
    return std::sqrt(t / (size - 1));
}
inline double norm(const my_vector& obj) {
    double t = 0;
    for (auto e : obj) t += e * e;
    return std::sqrt(t);
}

追記

上記のヘッダーをgccでコンパイルすると以下のエラーが発生する。

error: invalid initialization of non-const reference of type 'my_vector& {aka std::vector<double>&}' 
from an rvalue of type 'my_vector {aka std::vector<double>}'
     return my_vector(lhs) += rhs;
            ^~~~~~~~~~~~~~
note:   initializing argument 1 of 'my_vector& operator+=(my_vector&, const my_vector&)'
 inline my_vector& operator+=(my_vector& lhs, const my_vector& rhs) {

一時的に生成される無名のオブジェクト(rvalue)を使用して、non-const referenceを初期化することはできないという意味らしい。以下のように修正すればコンパイルエラーは発生しない。

// 変更前
inline my_vector operator+(const my_vector& lhs, const my_vector& rhs) {
    return my_vector(lhs) += rhs;
}

// 変更後
inline my_vector operator+(const my_vector& lhs, const my_vector& rhs) {
    my_vector t(lhs);
    return t += rhs;
}

生成したオブジェクトを変数に割り当てて、lvalueにしている。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?