变长参数模版函数初探

最开始在写一个 命令模块, 涉及到 简单命令 和 复合命令。
所有的命令 是通过字符串组装的。
命令的调用是通过注册机制 实现绑定的。
具体的功能封装在对应的 功能类里面。
由于复合命令的存在,会导致一条命令 执行多个处理。
所以希望在 注册的时候,能够直接将多个对象直接保存到一个容器内。
这就会涉及到 不定长参数 保存的 过程。
在这里我才用了变长参数模版。

我先定义一个通用的 key-value 的 变长模版, 用于构造一个容器对象。
指定 当输入类型 为 key-value:string-string时,对应的处理方法。
当然也可以指定其他类型的参数和对应的处理函数。

template<typename... Params>
MapSet Register(string key, string value, Params... params) {
    auto map_set = Register(params...);
    map_set.add(key, value);
    return map_set;
}

设定模版扩展的终止条件

template<typename... Params>
MapSet Register() {
    return MapSet("null");
}

这样 就能把想要的参数保存在对应的容器中。

在使用变长模版函数的过程中,我在想 每个函数都构造一个对象, 会导致接收的时候都调用拷贝构造。
所以我在定义容器的时候,定义了拷贝构造,和右值引用构造,方便查看调用过程。
最开始,我没有实现 右值引用,只是实现拷贝构造

    MapSet(const MapSet& map_set) {
        dictory_ = map_set.dictory_;
        index = AddRef();
        cout << "construct from : const Copy, index :" << index << endl;
    }
    MapSet(MapSet& map_set) {
        dictory_ = map_set.dictory_;
        index = AddRef();
        cout << "construct from : Copy, index :" << index << endl;
    }

结果如图:
这里写图片描述

后来加入 右值引用

    MapSet(MapSet&& map_set) {
        dictory_.swap(map_set.dictory_);
        index = AddRef();
        cout << "construct from : Swap, index :" << index << endl;
    }
}

结果如图:
这里写图片描述
发现 没有触发右值引用

再次修改代码

template<typename... Params>
MapSet Register(string key, string value, Params... params) {
    auto map_set = Register(params...);
    map_set.add(key, value);
    return std::move(map_set);
}

结果如图:
这里写图片描述

现在已经触发了 右值引用, 其中8次构造 发生了 7次交换。
后来朋友告诉我 c++ 有返回值优化,于是 去掉std::move,把debug 编译 换成release 编译 再次尝试。

template<typename... Params>
MapSet Register(string key, string value, Params... params) {
    auto map_set = Register(params...);
    map_set.add(key, value);
    return map_set;
}

结果如图:
这里写图片描述
这里产生2次构造,其中发生一次交换。

这里不同的编译器优化效果可能不一样,下面使用 blade 编译的
这里写图片描述

完整代码:


#include <iostream>
#include <string>
#include <map>

using namespace std;

int AddRef() {
    static int ref = 0;
    return ref++;
}

class MapSet{
public:
    MapSet(string info = "") {
        index = AddRef();
        cout << "construct from : " << info << ", index :" << index << endl;
    }

    MapSet(const MapSet& map_set) {
        dictory_ = map_set.dictory_;
        index = AddRef();
        cout << "construct from : const Copy, index :" << index << endl;
    }

    MapSet(MapSet& map_set) {
        dictory_ = map_set.dictory_;
        index = AddRef();
        cout << "construct from : Copy, index :" << index << endl;
    }

    MapSet(MapSet&& map_set) {
        dictory_.swap(map_set.dictory_);
        index = AddRef();
        cout << "construct from : Swap, index :" << index << endl;
    }

    void add(string key, string value) {
        dictory_.emplace(std::make_pair(key, value));
    }
    void print() {
        cout << "output" << endl;
        for (auto it : dictory_) {
            cout << it.first << " : " << it.second << endl;
        }

    }
private:
    map<string, string> dictory_;
    int index;
};

template<typename... Params>
MapSet Register() {
    return MapSet("null");
}

template<typename... Params>
MapSet Register(string key, string value, Params... params) {
    auto map_set = Register(params...);
    map_set.add(key, value);
    return map_set;
}


int main() {
    Register("a", "a", "b", "b", "c", "c", "d", "d", "e", "e", "f", "f").print();

    getchar();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值