c++更通用的运算符模板

发布于 2024-12-06 10:05:19 字数 710 浏览 2 评论 0原文

所以我刚刚学习了(谢谢大家)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;
}  

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

我打赌不是,但那就太好了!

So I just learned (thanks guys) about decltype. I now can write really nice vector templates that actually outperform 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;
}  

Is it possible to make this kind of templating even more "meta", in the sense that we allow the operator ("*") itself to be a template parameter? I.e. have one single template definition that works for *, +, %, etc, where the appropriate operator op is used in *c = (*a) op (*b)?

I'm betting it is not, but it would be nice!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

樱花落人离去 2024-12-13 10:05:19

正如您所预料的,答案是“不”。 :)

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

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

OPERATOR_BLOB(*)
OPERATOR_BLOB(+)
…

As you expected, this answer is "no." :)

However, you can use the preprocessor to generate such functions:

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

OPERATOR_BLOB(*)
OPERATOR_BLOB(+)
…
Oo萌小芽oO 2024-12-13 10:05:19

使用 std::declval() 而不仅仅是 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); \
    }

Use std::declval<T&&>() instead of just T(), it might not have a default constructor (since std::vector does not require a default constructor, only a copy constructor). Also, be very sure about type & reference & rvalue reference correctness and forwarding, classes may implement things differently for values, references, const references, rvalue references. Test it with several classes.

Also, mind you that the return type extraction might not work for compound assignment operators in GCC due to an unimplemented feature.

And yes, I solved it with parameterized macros in my pointer wrapper class: http://frigocoder.dyndns.org/code/Frigo/Lang/ref

For example

#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); \
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文