使用重载的逗号运算符初始化数组 [英] Using overloaded comma operator for initializing arrays

查看:134
本文介绍了使用重载的逗号运算符初始化数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找改进我们的矢量库的想法。在Boost :: uBlas中,我偶然发现了对Blitz ++的引用,它为初始化小尺寸矢量(和矩阵)提供了一种非常简洁的方法:

I''m currently looking for ideas to improve our vector library. In Boost::uBlas I stumbled on a reference to Blitz++, which provdies a very neat looking method for initializing small sized vectors (and matrices):

Array<float,2> A(3,3); //two-dimensional 3-by-3 array of float
A = 1, 2, 3,
    4, 5, 6,
    7, 8, 9;



我无法确定lib的实际下载链接,但经过一番思考后,我想出了一种方法来实现支持上述语法的东西:


I couldn''t pin down an actual download link for the lib, but after some thought I came up with a way to implement something that supports the above syntax:

#include <iostream>

template <int N> class Tuple; // forward decl
template <int N, int M>
class TupleArgs {
public:
   Tuple<N>* tuple;
   Tuple<M>* uninitialized;
   TupleArgs(Tuple<N>* t, Tuple<M>* u) : tuple(t), uninitialized(u) {}
};

template <int N>
class Tuple {
public:
   double head;
   Tuple<N-1> tail;

   Tuple() : head(0) {}

   TupleArgs<N, N-1> operator=(double a) {
      head = a;
      return TupleArgs<N, N-1>(this, &tail);
   }

   Tuple<N>& operator=(const Tuple<N>& other) {
      head = other.head;
      tail = other.tail;
      return *this;
   }
};
template <>
class Tuple<1> {
public:
   Tuple<1>() : head(0) {}
   Tuple<1>(double a) : head(a) {}
   Tuple<1>& operator=(const Tuple<1>& other) {
      head = other.head;
      return *this;
   }
   double head;
};
template <int N, int M>
TupleArgs<N, M-1> operator,(TupleArgs<N, M>& a, double b) {
   a.uninitialized->head = b;
   return TupleArgs<N, M-1>(a.tuple, &a.uninitialized->tail);
}
template <int N>
Tuple<N>& operator,(TupleArgs<N,1>& a, double b) {
   a.uninitialized->head = b;
   return *a.tuple;
}

int _tmain(int argc, _TCHAR* argv[])
{
   Tuple<3> triple;
   triple = 4, 5, 6;
   std::cout << triple.head << ' ' << triple.tail.head << ' ' << triple.tail.tail.head << ' ' << std::endl;
   Tuple<9> matrix33;
   matrix33 = 1, 2, 0,
              4, 5, 3,
              7, 8, 2;
   // use your debugger if you want to check that this really works
   return 0;
}



不幸的是,虽然我发现不仅有一种方法可以使用这种初始化语法,但对于任意(固定)大小的数组也是如此,所有这一切都需要付出代价:



1.覆盖逗号运算符会破坏它通常的尊重(从左到右)评估顺序的行为:初始化程序列表将以任意顺序进行评估

2.我必须提供一个具有双重值的隐含可用的构造函数,并允许编译器隐式地将double类型的变量或表达式转换为元组。如果有人在想要元组时意外使用 double ,则该错误将无法被检测到,并且可能是以后很难察觉。实际上,C ++类型的安全性受到了损害。

3.由于逗号运算符的优先级极低(低于赋值),因此使用表达式初始化数组需要将其括在括号中。如果不这样做,可能会以许多不可预见的方式破坏代码。并且可能中断将是静默的(即编译器可能无法指出问题)。

4.元组赋值运算符不能直接链接:上述赋值表达式的值确实是正确类型(元组),但链接赋值的唯一方法是将整个赋值括在括号中:


Unfortunately, while I''ve found not only a way to use this kind of initialization syntax but did so for arbitrary (fixed) size arrays, all this comes at a cost:

1. overriding the comma operator destroys it''s usual behaviour of respecting (left to right) evaluation order: the expressions in the initializer list will be evaluated in arbitrary order
2. I had to provide an implicitely usable constructor taking a double value, and that allows the compiler to implicitely convert variables or expressions of type double to Tuple. If someone accidentally uses a double when he intended a Tuple, that mistake won''t be detected, and may be hard to detect later. Effectively, the C++ type safety is compromised.
3. Since the comma operator has extremely low priority (lower than assignment), intializing an array with an expression requires enclosing it in parenthesis. Failure to do so can break the code in many unforseeable ways. And potentially the break will be silent (i. e. the compiler may not be able to point out the problem).
4. The Tuple assignment operator cannot be chained directly: the values of the above assignment expressions are indeed of the correct type (Tuple), but the only way to chain the assignment is by enclosing the entire assignment in brackets:

Tuple<3> triple1, triple2;
triple1 = triple2 = 1, 2, 3; // error: the left assignment tries to assign the
                             // result of (triple2 =1), which has the wrong type
triple1 = (triple2 = 1, 2, 3); // ok, but ugly(





我的问题:

是否有可能避免上述大部分缺点?我意识到第1项可以''得到帮助,但我不知道其他三个......



PS:

1.我已经钻研了之前的库,但鉴于他们的设计语法,我还没有找到Boost :: Spirit的核心,它也使用了这种初始化语法。如果有人知道Boost :: Spirit,那么就能理解所使用的机制在那里,也许他可以指出相关的文章/文件/我需要知道的任何内容来改善上述内容。

2.如上所述,我找到了Blitz ++但我无法确定实际图书馆的工作下载链接。似乎不再支持,但我想知道原始源代码是否仍然可用某个地方?



PPS:对不起这个问题很遗憾,但我相信所有这些信息都需要指出我已经知道的东西 - 无论如何这个论坛被称为快速答案,而不是快速的问题;)



My question:
Is it possible to avoid most of the drawbacks outlined above? I realize that item 1 can''t be helped, but I wonder about the other three...

P.S.:
1. I''ve delved in the boost libraries before, but given their contrived syntax I haven''t (yet) found the heart to check out Boost::Spirit, which also uses this kind of initialization syntax. If someone knows Boost::Spirit well enough to understand the mechanics used there, maybe he can point me to the relevant articles/bits of documentation/whatever I''d need to know to improve the above.
2. As mentioned above, I''ve found the Blitz++ documentation. But I couldn''t pinpoint a working download link for the actual ibrary. It seems that it''s no longer supported, but I wonder if the original source code is still available somewhere?

P.P.S.: sorry for the long question, but I believe all this information is required to point out what I already know - and anyway this forum is called quick answers, not quick questions ;)

推荐答案

逗号运算符重载是一个宇宙特征。



这里更多建议而不是解决方案:



Comma operator overloading is a cosmic feature.

Here more a suggestion than a solution:

#include <iostream>

template <class T, int N> class Tuple; // forward decl
template <class T, int N, int M>
class TupleArgs {
public:
   Tuple<T, N>* tuple;
   Tuple<T, M>* uninitialized;
   TupleArgs(Tuple<T, N>* t, Tuple<T, M>* u) : tuple(t), uninitialized(u) {}
};

template <class T, int N>
class Tuple {
public:
   T head;
   Tuple<T, N-1> tail;

   Tuple() : head(0) {}

   TupleArgs<T, N, N-1> operator=(T a) {
      head = a;
      return TupleArgs<T, N, N-1>(this, &tail);
   }

   Tuple<T, N>& operator=(const Tuple<T, N>& other) {
      head = other.head;
      tail = other.tail;
      return *this;
   }
};

template <class T>
class Tuple<T, 1> {
public:
   Tuple<T, 1>() : head(0) {}
   Tuple<T, 1>(T a) : head(a) {}
   Tuple<T, 1>& operator=(const Tuple<T, 1>& other) {
      head = other.head;
      return *this;
   }
   T head;
};

template <class T, int N, int M>
TupleArgs<T, N, M-1> operator,(TupleArgs<T, N, M>& a, T b) {
   a.uninitialized->head = b;
   return TupleArgs<T, N, M-1>(a.tuple, &a.uninitialized->tail);
}
template <class T, int N>
Tuple<T, N>& operator,(TupleArgs<T, N, 1>& a, T b) {
   a.uninitialized->head = b;
   return *a.tuple;
}

int _tmain(int argc, _TCHAR* argv[])
{
   Tuple<int, 3> triple;
   triple = 4, 5, 6;
   std::cout << triple.head << ' ' << triple.tail.head << ' ' << triple.tail.tail.head << ' ' << std::endl;
   Tuple<int, 9> matrix33;
   matrix33 = 1, 2, 0,
              4, 5, 3,
              7, 8, 2;
   // use your debugger if you want to check that this really works

   Tuple<int, 3> triple1, triple2;
   //triple1 = triple2 = 1, 2, 3; // error: the left assignment tries to assign the
                                // result of (triple2 =1), which has the wrong type
   //triple1 = (triple2 = 1, 2, 3); // ok, but ugly(

   triple1 = 1, 2, 3;
   triple2 = triple1;

   return 0;
}





使用int作为T它有效很好,有双倍作为T它不起作用。



也许是上面提到的编译器错误?



我的环境:VS2010,SP1Rel



祝你好运



With int as T it works fine, with double as T it doesn''t work.

Perhaps the upper mentioned compiler bug?

My environment : VS2010, SP1Rel

Best regards


不要这样做......你已经注意到了它有很多缺点。



如果它完全支持,我可以建议你使用初始化列表(C ++ 11特性),但支持仍然很少Visual Studio 2012.



或者,如果您使用的是较旧的编译器,您可能希望使用struct(不带构造函数)。
Don''t do it... As you have noticed, it come with a lot of drawback.

If it was fully supported, I could recommand you to use initializer list (C++ 11 feature) but support is still marginal in Visual Studio 2012.

Alternatively, you might want to uses struct (without constructor) if you are using and older compiler.


这篇关于使用重载的逗号运算符初始化数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆