【问题标题】:c++ even more generalized operator templatingc++ 更通用的运算符模板
【发布时间】:2011-09-26 12:44:02
【问题描述】:

所以我刚刚学习了(谢谢大家)关于 decltype 的知识。我现在可以编写非常好的矢量模板,实际上优于 valarrays(!):

template <typename T, typename U>
vector<decltype(T()*U())> operator*(const vector<T>& A, const vector<U>& B){
  vector<decltype(T()*U())> C = vector<decltype(T()*U())>(A.size());
  typename vector<T>::const_iterator a = A.begin();
  typename vector<U>::const_iterator b = B.begin();
  typename vector<decltype(T()*U())>::iterator c = C.begin();
  while (a!=A.end()){
    *c = (*a) + (*b);
    a++; b++; c++;
  }
  return C;
}  

在我们允许运算符(“*”)本身作为模板参数的意义上,是否有可能使这种模板更加“元”? IE。有一个适用于 *、+、% 等的模板定义,其中在 *c = (*a) op (*b) 中使用了适当的运算符 op?

我打赌它不是,但它会很好!

【问题讨论】:

  • 这本质上是accumulate 的二进制版本,尽管accumulate 本身已经可以用于类似的东西,虽然不是那么对称。不过,真正的力量可能来自惰性评估包装器。
  • ... 吹毛求疵:您可能希望对Creserve 使用默认构造以确保它不需要增长,然后使用push_back(而不是创建数组的大小 --awkwardly 与 vector&lt;x&gt; c = vector&lt;x&gt;( a.size() )-- 并重写元素)。使用类型定义!它们有助于提高可读性,单个typedef decltype( A.front()*B.front() ) result_type 将使代码更具可读性。避免向泛型代码添加不必要的要求(当前实现使用T()U()result_type() 强加了默认构造函数的存在)
  • @DavidRodríguez-dribeas:我发现使用 push_back 比完整的声明/重写版本慢得多,在我的测试用例中慢了 50%。
  • @KerrekSB:我将不得不检查惰性评估包装器,我对它们一无所知。
  • @andyInCambridge:您执行测试的设置是什么?您是否提前预订空间?请注意,reserve() 调用将产生巨大的影响,因为它将确保发生单个内存分配(假设您保留了适当的大小),在这种情况下,它应该比您的方法更快。如果不是,我很想知道您正在运行什么编译器、平台和测试...

标签: c++ templates operators


【解决方案1】:

如您所料,这个答案是“不”。 :)

但是,您可以使用预处理器来生成此类函数:

#define OPERATOR_BLOB(optype) \
    vector<…> operator optype (…) { … }

OPERATOR_BLOB(*)
OPERATOR_BLOB(+)
…

【讨论】:

    【解决方案2】:

    使用std::declval&lt;T&amp;&amp;&gt;() 而不仅仅是T(),它可能没有默认构造函数(因为std::vector 不需要默认构造函数,只需要一个复制构造函数)。此外,请非常确定关于类型、引用和右值引用的正确性和转发,类可能对值、引用、const 引用、右值引用实现不同的事物。用几个类对其进行测试。

    另外,请注意,由于未实现的功能,返回类型提取可能不适用于 GCC 中的复合赋值运算符。

    是的,我在指针包装类中使用参数化宏解决了这个问题:http://frigocoder.dyndns.org/code/Frigo/Lang/ref

    例如

    #define PROXY_BINARY_OPERATOR(_) \
        template <class Arg> \
        decltype(std::declval<T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) \
        { \
            return std::forward<T>(get()) _ std::forward<Arg>(arg); \
        } \
        template <class Arg> \
        decltype(std::declval<const T&&>() _ std::declval<Arg&&>()) operator _ (Arg&& arg) const \
        { \
            return std::forward<T>(get()) _ std::forward<Arg>(arg); \
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 2012-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-08
      相关资源
      最近更新 更多