1. 程式人生 > 其它 >c++可變模板函式的非遞迴化實現

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);
...

完美!!!