c++ - 可变参数模板运算符<<

标签 c++ operator-overloading variadic-templates

我正在尝试更改我的一些功能 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<<() 接口(interface) struct bar 的用户-- 当然,不改变 foo()语义。

万一没办法通过class T...作为 operator<<() 的参数, 该函数自然会比 foo() 效率低,因为它会被多次调用。是否有任何合理的 C++ 构造,或者坚持 foo()是这里唯一/最好的选择吗?

上下文:

这些 foo()函数是网络通信的发送者/接收者。我认为最好提供一个更“C++”的接口(interface),发送者/接收者流,可写/可读使用 <<>>运算符——除了使用常规函数 foo(...) .

最佳答案

语言正在做您要求它做的事情。

对于关联性,以下是等价的(<<>> 是从左到右关联的):

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(...) 一样快.

关于c++ - 可变参数模板运算符<<,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17868718/

相关文章:

operator-overloading - 如何求两个 float 的平均值

c++ - 重载赋值运算符 带下标运算符

c++ - 在 C++11 中实现元函数 zip

c++ - 获取 C++ 函数参数的类型

c++ - 为什么这两个打印整数二进制表示的函数具有相同的输出?

c++ - 如何使用 std::generate_canonical 生成范围 [0,1) 内的随机数?

c++ - boost::archive::xml_iarchive 因 xml(反序列化上下文)而失败

c++ - 我怎样才能 "override"[] 在 C++ 中接受两个参数?

c++ - 可能发生包扩展的上下文

c++ - 调试断言失败