zoukankan      html  css  js  c++  java
  • c++可变模板函数的非递归化实现

    在C++primer p618中介绍了递归实现的版本,主要的形式:

    
    template<typname ARGS>
    void print(const T&t,const ARGS&... rest)
    {
        print(t);
        print(t,rest...);
    }
    
    template<typename T>
    void print(const T& t)
    {
    }
    

    这样的写法又长又臭,有没有更简便的方法呢?
    比如我想用openssh的sha进行哈希,其主要过程是

    SHA256CTx ctx;
    CTXINIT(&ctx);
    
    CTXUPDATE(&ctx,(const void*)data,bytesize);
    ...
    
    CTXFINLIZE(&result,&ctx);
    

    假如我有多个类型要一起进行哈希的数据,比如int,long,vector,string。如何优雅的写出模板函数呢:(假定已看过effective modern c++里的标签分派 p176)

    auto result=computeHash(int,long,vector,string...);
    

    可以利用逗号表达式与initializer_list。
    C/C++语言中的逗号表达式:a=(b+c,d),其结果是a=d。依次求值,并取最后一个表达式的结果为最终值。
    initializer_list:要求内容在编译期就已知,选这个我感觉是有点无奈,C++应该有更优雅的方式来实现非递归模式的。

    下面上代码:

    #include <bits/stdc++.h>
    #include <openssl/sha.h>
    
    using namespace std;
    
    using HashType = array<uint8_t, SHA256_DIGEST_LENGTH>;
    
    template <typename... ARGS>
    HashType computeHash(const ARGS &...args)
    {
        SHA256_CTX ctx;
        SHA256_Init(&ctx);
        std::initializer_list<int>{(internalCompute(&ctx, args, std::is_arithmetic<std::decay_t<ARGS>>()), 0)...};
        HashType result;
        SHA256_Final(result.data(), &ctx);
        return result;
    }
    
    template <typename T>
    void internalCompute(SHA256_CTX *ctx, const T &data, std::true_type)
    {
        const void *underlying = static_cast<const void *>(&data);
        SHA256_Update(ctx, underlying, sizeof(T));
    }
    
    template <typename T>
    void internalCompute(SHA256_CTX *ctx, const T &container, std::false_type)
    {
        using DataType = typename T::value_type;
        const void *underlying = static_cast<const void *>(container.data());
        size_t size = container.size() * sizeof(DataType);
        SHA256_Update(ctx, underlying, size);
    }
    
    
    int main(int argc, char **argv)
    {
        std::string test1 = "123456";
        uint8_t a = 1;
        uint64_t b = 2;
        auto hash = computeHash(test1, a, b);
    }
    

    可以注意到

    std::initializer_list<int>{(internalCompute(&ctx, args, std::is_arithmetic<std::decay_t<ARGS>>()), 0)...};
    

    这个句子才是最为关键的,对每个模板参数依次compute,并依照是否是容器还是数值进行标签分派。因为扩展" ... "在括号外,所以也可以看成:

    compute(&ctx,arg1,ARG1);
    compute(&ctx,arg2,ARG2);
    ...
    

    完美!!!

  • 相关阅读:
    【转】织梦为栏目添加图片的方法
    写在php设计模式前
    memcache 开机启动
    php 列出当前目录
    print echo 的区别
    php 报错等级
    nginx 启动脚本
    centos 编译 安装php
    修改linux iptable规则
    linux yum 安装软件
  • 原文地址:https://www.cnblogs.com/manch1n/p/15484791.html
Copyright © 2011-2022 走看看