c ++ Принудительное неявное преобразование при передаче в качестве аргумента. - PullRequest
0 голосов
/ 16 декабря 2018

У меня проблема с неявными преобразованиями в C ++.

Я пытаюсь создать шаблон Expression для векторной арифметики (я знаю, что такие же библиотеки уже существуют. Я просто изучаю C ++, поэтому я хотел попробоватьчто-то с шаблонами).

Я хотел бы создать класс Vector, который может вычислять следующим образом:

simd::test::Vector<char, 5> a;
simd::test::Vector<short, 5> b;

auto ret = a + b + a + b;

, где на выходе будет Vector шорт, потому что short - это больший типчем char.

Прямо сейчас у меня есть класс, который может добавлять векторы одинаковых типов данных.Для разных типов я должен вызвать явное преобразование:

//simd::test::Vector<short, 5>(a)
auto ret = simd::test::Vector<short, 5>(a) + b + simd::test::Vector<short, 5>(a) + b;

Возможно ли неявное преобразование Vector перед передачей в функцию "operator + ()"?Вот мой код Vector:

#pragma once

#include <type_traits>

namespace simd {
  namespace test {

  template<typename R, std::size_t Dim,
      typename std::enable_if<std::is_arithmetic<R>::value>::type* = nullptr
  >
  class Vector_expression {
    public:
      static constexpr std::size_t size = Dim;

      virtual const R operator[] (std::size_t index) const = 0;

      virtual ~Vector_expression() = default;

  };

  template<typename T, std::size_t Dim>
  class Vector final : public Vector_expression<T, Dim> {
    private:
      T data[Dim];
    public:
      Vector() = default;

      template<typename R>
      Vector(const Vector_expression<R, Dim> &obj) {
        for(std::size_t index = 0; index < Dim; ++index) {
          data[index] = obj[index];
        }
      }

      template<typename R>
      Vector(Vector_expression<R, Dim> &&obj) {
        for(std::size_t index = 0; index < Dim; ++index) {
          data[index] = obj[index];
        }
      }

      template<typename R>
      Vector<T, Dim> & operator=(const Vector_expression<R, Dim> &obj) {
        for(std::size_t index = 0; index < Dim; ++index) {
          data[index] = obj[index];
        }
        return (*this);
      }

      template<typename R>
      Vector<T, Dim> & operator=(Vector_expression<R, Dim> && obj) {
        for(std::size_t index = 0; index < Dim; ++index) {
          data[index] = obj[index];
        }
        return (*this);
      }

      virtual const T operator[] (std::size_t index) const override {
        return data[index];
      }

      T & operator[] (std::size_t index) {
        return data[index];
      }

      virtual ~Vector() = default;
    };

    template<typename E1, typename E2, typename R, std::size_t Dim>
    class Vector_sum final : public Vector_expression<R, Dim> {
      private:
        const E1 & _lhs;
        const E2 & _rhs;
      public:
        Vector_sum() = delete;

        Vector_sum(const E1 & lhs, const E2 & rhs) :
            _lhs(lhs),
            _rhs(rhs)
        {}

        virtual const R operator[] (std::size_t index) const override {
          return _lhs[index] + _rhs[index];
        }

        virtual ~Vector_sum() = default;
    };

    template<typename R, std::size_t Dim>
    Vector_sum<Vector_expression<R, Dim>, Vector_expression<R, Dim>, R, Dim> operator+ (const Vector_expression<R, Dim> & lhs, const Vector_expression<R, Dim> & rhs) {
      return {lhs, rhs};
    }

  }
}

Ответы [ 2 ]

0 голосов
/ 16 декабря 2018

Просто определите operator+, который допускает разные типы аргументов.Один улов определяет тип элемента результирующей суммы.Вероятно, лучший вариант - использовать любой результат добавления двух элементов.Один из способов написать этот тип:

decltype(std::declval<const R1>() + std::declval<const R2>())

Или, если вы знаете, что типы являются встроенными арифметическими типами, это будет то же самое, что и

std::common_type_t<R1, R2>

Или с использованием конечного возврататипа, мы можем воспользоваться параметрами функции, чтобы сократить выражения std::declval:

template<typename R1, typename R2, std::size_t Dim>
auto operator+ (const Vector_expression<R1, Dim> & lhs,
                const Vector_expression<R2, Dim> & rhs)
-> Vector_sum<Vector_expression<R1, Dim>, Vector_expression<R2, Dim>,
              decltype(lhs[0] + rhs[0]), Dim>
{
  return {lhs, rhs};
}
0 голосов
/ 16 декабря 2018

Это можно сделать с помощью шаблонов и std::common_type, примерно так:

template<typename T1, typename T2, size_t S>
simd::test::Vector<typename std::common_type<T1, T2>::type, S>
operator+(simd::test::Vector<T1, S> const& v1,
          simd::test::Vector<T2, S> const& v2)
{
    // TODO: Implementation...
}
...