c ++强制隐式转换作为参数传递

c++ Force implicit conversion on pass as argument

我对 C++ 中的隐式转换有疑问。

我正在尝试为矢量算术创建一些表达式模板(我知道相同的库已经存在。我只是在学习 C++,所以我想尝试使用模板)。

我想创建 class 向量,它可以像这样计算:

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

auto ret = a + b + a + b;

,其中输出将是 Vector of shorts 因为 short 是比 char 更大的类型。

现在,我有 class 可以添加相同数据类型的向量。对于不同的类型,我必须调用显式转换:

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

  }
}

可以使用模板和 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...
}

只需定义一个允许不同参数类型的 operator+。一个问题是确定结果总和的元素类型。可能最好的选择是使用添加两个元素的任何结果。这种类型的一种写法是:

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

或者,如果您知道类型是内置算术类型,那将与

相同
std::common_type_t<R1, R2>

或者使用尾随 return 类型,我们可以利用函数参数来缩短 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};
}