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

时间:2018-12-16 15:07:02

标签: c++ implicit-conversion expression-templates

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

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

我想创建Vector类,它能够像这样计算:

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

auto ret = a + b + a + b;

,在输出上将是short的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;

是否可以在传递给函数“ operator +()”之前隐式转换Vector?这是我的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 :(得分:4)

只需定义一个允许不同参数类型的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};
}

答案 1 :(得分:3)

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