我正在尝试将我的一些函数foo()
更改为operator<<()
,只是为了获得一些“半C /半C ++”代码看起来更像C ++。但事实上,我已经陷入了以下转型步骤:
template <class... T>
inline const size_t foo(const T&... data) {
return sizeof...(T);
}
struct bar {
template <class... T>
inline const size_t operator<<(const T&... data) {
return sizeof...(T);
}
};
int main(int argc, char *argv[]) {
bar a;
std::cout << ">>> length " << foo(1, 2, 3) << std::endl;
std::cout << ">>> length " << (a << 1 << 2) << std::endl;
std::cout << ">>> length " << (a << 1 << 2 << 3) << std::endl;
std::cout << ">>> length " << (a << 1 << 2 << 3 << 4) << std::endl;
}
从输出中:
$ ./a.out
>>> length 3
>>> length 4
>>> length 32
>>> length 512
我得出结论,第一次计算是在a << 1
上执行的,随后的值会相应地移动。然而,我没有看到如何重写foo()
,以便为operator<<()
的用户提供struct bar
接口 - 当然,不会改变foo()
语义。
如果无法将class T...
作为参数传递给operator<<()
,则该函数自然会比foo()
效率低,因为它会被多次调用。是否有任何合理的C ++构造,或坚持foo()
是唯一/最好的选择吗?
上下文:
这些foo()
函数是网络通信的发送者/接收者。我认为最好提供一个更“C ++”的接口,带有发送器/接收器流,使用<<
和>>
运算符可写/可读 - 除了使用常规函数foo(...)
答案 0 :(得分:3)
语言正在按照你的要求去做。
对于关联性,以下内容是等效的(<<
和>>
是从左到右关联的):
a << 1 << 2
(a << 1) << 2
来电a << 1
会调用您的用户定义的运算符,该运算符又会返回size_t
。这就是为什么下一个调用的类型如下:size_t << int
(这是一个简单的按位移位)。
您需要使用表达式模板。这个想法如下( live example here ):
template<typename... args>
struct stream_op
{
};
template<typename... A, typename B>
stream_op<A..., B> operator<<(stream_op<A...> a, B b)
{
// Do stuff
}
因此,会发生以下情况(a
为stream_op<>
):
a << 1 << 2
------
|
v
-------------------------------------------
stream_op<int> operator<<(stream_op<>, int) << 2
-------------- ---
| |
| +---------------------------+
v v
-------------- ---
stream_op<int> << int
-------------- ---
| |
| +---------------------------+
+----------------------------+ |
v v
-------------- ---
stream_op<int,int> operator<<(stream_op<int>, int)
------------------
|
v
------------------
stream_op<int,int> // <- Expected result
然后你只需要设置一个方法将stream_op
转换为int(或任何你想要的)。
关于表演的说明:使用这些表达模板,部分数据按类型编码,因此通常应该与直接调用foo(...)
一样快。