1

我试图将我的一些函数更改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(...)

4

1 回答 1

5

The language is doing what you are asking it to do.

With associativity, the following are equivalent (<< and >> are left-to-right associative):

a << 1 << 2
(a << 1) << 2

The call a << 1 calls your user-defined operator, which in turn returns a size_t. That's why the types for next call are the following: size_t << int (which is a simple bitwise shift).

You need to use expression templates. The idea is the following (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
}

So, the following occur (with a as 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

Then you just have to put a method to convert stream_op to int (or to whatever you want).

A note on performances: with these expression templates, a part of the data is encoded in the type, so normally it should be as fast as a direct call to foo(...).

于 2013-07-25T21:39:24.017 回答