Я использую CRTP для перегрузки оператора. У меня есть базовая структура.
template<int S, typename T, typename C>
struct ColorModel {
constexpr static int SPACE = S;
ColorModel() {
std::fill(begin(), end(), 0);
}
ColorModel(const ColorModel& another) {
std::copy(another.begin(), another.end(), begin());
}
ColorModel(ColorModel&& another) noexcept {
std::move(another.begin(), another.end(), begin());
}
ColorModel(const std::initializer_list<T>& l) {
std::copy(l.begin(), l.end(), begin());
}
explicit ColorModel(const T& elem) {
std::fill(begin(), end(), elem);
}
constexpr inline const T* cbegin() const {
return static_cast<const C*>(this)->components.cbegin();
}
constexpr inline const T* cend() const {
return static_cast<const C*>(this)->components.cend();
}
constexpr inline const T* begin() const {
return cbegin();
}
constexpr inline const T* end() const {
return cend();
}
constexpr inline T* begin() {
return static_cast<C*>(this)->components.begin();
}
constexpr inline T* end() {
return static_cast<C*>(this)->components.end();
}
constexpr inline size_t size() const {
return std::distance(begin(), end());
}
constexpr inline ColorModel& operator=(const ColorModel& rhs) {
std::copy(rhs.begin(), rhs.end(), begin());
return *this;
}
constexpr inline ColorModel& operator=(ColorModel&& rhs) noexcept {
std::move(rhs.begin(), rhs.end(), begin());
return *this;
}
constexpr inline ColorModel& operator=(const T& rhs) {
std::fill(begin(), end(), rhs);
return *this;
}
constexpr inline ColorModel& operator=(T&& rhs) {
std::fill(begin(), end(), rhs);
return *this;
}
constexpr inline ColorModel& operator+=(const ColorModel& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::plus<>());
return *this;
}
constexpr inline ColorModel& operator+=(ColorModel&& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::plus<>());
return *this;
}
constexpr inline ColorModel& operator+=(const T& rhs) {
util::transform(begin(), end(), rhs, begin(), std::plus<>());
return *this;
}
constexpr inline ColorModel& operator+=(T&& rhs) {
util::transform(begin(), end(), rhs, begin(), std::plus<>());
return *this;
}
constexpr inline ColorModel& operator-=(const ColorModel& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::minus<>());
return *this;
}
constexpr inline ColorModel& operator-=(ColorModel&& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::minus<>());
return *this;
}
constexpr inline ColorModel& operator-=(const T& rhs) {
util::transform(begin(), end(), rhs, begin(), std::minus<>());
return *this;
}
constexpr inline ColorModel& operator-=(T&& rhs) {
util::transform(begin(), end(), rhs, begin(), std::minus<>());
return *this;
}
constexpr inline ColorModel& operator*=(const ColorModel& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::multiplies<>());
return *this;
}
constexpr inline ColorModel& operator*=(ColorModel&& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::multiplies<>());
return *this;
}
constexpr inline ColorModel& operator*=(const T& rhs) {
util::transform(begin(), end(), rhs, begin(), std::multiplies<>());
return *this;
}
constexpr inline ColorModel& operator*=(T&& rhs) {
util::transform(begin(), end(), rhs, begin(), std::multiplies<>());
return *this;
}
constexpr inline ColorModel& operator/=(const ColorModel& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::divides<>());
return *this;
}
constexpr inline ColorModel& operator/=(ColorModel&& rhs) {
std::transform(begin(), end(), rhs.begin(), begin(), std::divides<>());
return *this;
}
constexpr inline ColorModel& operator/=(const T& rhs) {
util::transform(begin(), end(), rhs, begin(), std::divides<>());
return *this;
}
constexpr inline ColorModel& operator/=(T&& rhs) {
util::transform(begin(), end(), rhs, begin(), std::divides<>());
return *this;
}
constexpr inline ColorModel operator+(const ColorModel& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::plus<>());
return result;
}
constexpr inline ColorModel operator+(ColorModel&& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::plus<>());
return result;
}
constexpr inline ColorModel operator+(const T& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::plus<>());
return result;
}
constexpr inline ColorModel operator+(T&& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::plus<>());
return result;
}
constexpr inline ColorModel operator-(const ColorModel& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::minus<>());
return result;
}
constexpr inline ColorModel operator-(ColorModel&& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::minus<>());
return result;
}
constexpr inline ColorModel operator-(const T& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::minus<>());
return result;
}
constexpr inline ColorModel operator-(T&& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::minus<>());
return result;
}
constexpr inline ColorModel operator*(const ColorModel& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::multiplies<>());
return result;
}
constexpr inline ColorModel operator*(ColorModel&& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::multiplies<>());
return result;
}
constexpr inline ColorModel operator*(const T& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::multiplies<>());
return result;
}
constexpr inline ColorModel operator*(T&& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::multiplies<>());
return result;
}
constexpr inline ColorModel operator/(const ColorModel& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::divides<>());
return result;
}
constexpr inline ColorModel operator/(ColorModel&& rhs) const {
ColorModel result;
std::transform(begin(), end(), rhs.begin(), result.begin(), std::divides<>());
return result;
}
constexpr inline ColorModel operator/(const T& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::divides<>());
return result;
}
constexpr inline ColorModel operator/(T&& rhs) const {
ColorModel result;
util::transform(begin(), end(), rhs, result.begin(), std::divides<>());
return result;
}
};
template<int S, typename T, typename C>
std::ostream& operator<<(std::ostream& os, const ColorModel<S, T, C>& model) {
for (const auto& elem : model) {
os << elem << " ";
}
return os;
}
А это потомок базовой структуры
struct RGB : ColorModel<0, int, RGB> {
std::array<int, 3> components;
RGB() : ColorModel() {
}
RGB(const RGB& other) : ColorModel(other) {
}
RGB(RGB&& other) : ColorModel(other) {
}
RGB(const std::initializer_list<int>& l) : ColorModel(l) {
}
explicit RGB(const int& elem) : ColorModel(elem) {
}
using ColorModel<0, int, RGB>::operator=;
};
Вот код моей функции util::transform
namespace util {
template<typename Iterator, typename T, typename BinaryOperator>
void transform(Iterator begin, Iterator end, const T& elem, Iterator result, BinaryOperator anOperator) {
for (; begin != end; ++begin, ++result) {
*result = anOperator(*begin, elem);
}
}
}
Но когда я начал тестировать его в main.cpp
, я получил странные результаты.
int main() {
RGB rgb1{1, 2, 3};
RGB rgb2{2, 3, 4};
RGB rgb3(10);
rgb3 += rgb3 + rgb1+rgb2;
std::cout << rgb3 << std::endl << rgb1 << std::endl << rgb2;
}
Я получаю 10 15 20
вместо 13 15 17
, и я застрял, пытаясь выяснить причину. Спасибо заранее.
P.S. Извините за все встроенные constexpr, я просто тестировал что-то локально.
util
? У вас там свои функции? - person cigien   schedule 04.12.2020return result;
из локальной переменной базового класса, разве это не срез? Может я что-то упускаю, я мало делаю CRTP. - person Eljay   schedule 04.12.2020RGB() : components{}, ColorModel() {}
? - person Kostas   schedule 04.12.2020