Reputation: 77
I am attempting to implement the SHA256 hash-function for use in-program with some compile-time abilities. A step in the pre-processing is padding the message/ input data given a formula. The amount of padding naturally has to be a positive integer. The algorithm relies on chunk processing and each chunk can only hold so much data, so if the data is larger than a chunk, we need more chunks. I solved this using recursion, but this throws C1202 - A template definition was recursive or exceeded complexity limits.
template <uint32_t DataLength, uint32_t ChunkSize, uint32_t Chunks>
int GetBitsToAppend() {
static int BitsToAppend = ChunkSize*Chunks - DataLength - 1 - (ChunkSize / 8);
return 0 > BitsToAppend ? GetBitsToAppend<DataLength, ChunkSize, Chunks+1>() : BitsToAppend;
}
I tried resolving it by adding an explicit template definition, but this instead throws a new error; C2768, Illegal use of explicit template arguments. Here is the code:
template<uint32_t DataLength, uint32_t ChunkSize>
int GetBitsToAppend<DataLength, ChunkSize, 1024>() {
int BitsToAppend = ChunkSize*Chunks - DataLength - 1 (ChunkSize / 8)
}
It works as intended if I use a normal recurring function, however this breaks due to the necessity of having the length of the processing-array being known at compile time. e.g:
int GetBitsToAppend(uint32_t DataLength, uint32_t ChunkSize, uint32_t Chunks) {
static int BitsToAppend = ChunkSize * Chunks - DataLength - 1 - (ChunkSize>>3);
return 0 > BitsToAppend ? GetBitsToAppend(DataLength, ChunkSize, Chunks+1) : BitsToAppend;
}
template <typename T, size_t OutputSize, size_t ByteSizeInput, size_t Rounds, size_t ChunkSize>
std::bitset<OutputSize> SHA(const T data) {
// Pre-processing
const uint32_t DataLength = ByteSizeInput << 3;
const uint32_t BitsToAppend = GetBitsToAppend(DataLength, ChunkSize, 1); // Run-time calculation
const uint32_t TargetSize = (DataLength + BitsToAppend + (ChunkSize>>3) + 1) / sizeof(uint32_t);
std::array<uint32_t, TargetSize> ProcessArray; // Invalid template argument.
// Copy data into ProcessArray and perform remaining preprocessing
//........
ChunkSize is constant and given by the template parameters of the function, and so is the ByteSizeInput. ChunkSize>>3 refers to the size of the integer being appended in in the pre-processing, being 64-bits in SHA256/224, and 128-bits in SHA384/512. Aka. respective chunk sizes divided by eight.
Does anyone know how to fix this?
Upvotes: 0
Views: 153
Reputation: 77
In addition to the answer provided kindly by mr. Sanders:
The compiler does not understand (in my experience) that the working template evaluates to constexpr when simply assigned to a variable, thus causing some further errors. Adding constepxr
to the function signature of GetBitsToAppend
as well as to BitsToAppend
and the sum variable TargetSize
provides the desired result:
template <uint32_t DataLength, uint32_t ChunkSize, uint32_t Chunks>
constexpr int GetBitsToAppend() {
constexpr int BitsToAppend = ChunkSize * Chunks - DataLength - 1 - (ChunkSize/8);
#pragma warning(suppress:4984) //Remove compatibility warning
if constexpr (0 > BitsToAppend)
return GetBitsToAppend<DataLength, ChunkSize, (Chunks+1)>();
else
return BitsToAppend;
}
template <typename T, size_t OutputSize, size_t ByteSizeInput, size_t Rounds, size_t ChunkSize>
std::bitset<OutputSize> SHA(const T data) {
//Pre-processing
constexpr uint32_t DataLength = ByteSizeInput << 3;
constexpr uint32_t BitsToAppend = GetBitsToAppend<DataLength, ChunkSize, 1>();
constexpr uint32_t TargetSize = (DataLength + BitsToAppend + (ChunkSize>>3)+1) / sizeof(uint32_t)
std::array<uint32_t, TargetSize> ProcessArray; // Compiles!
//...
Upvotes: 1
Reputation: 25388
In C++17 and later, this can be fixed by using if constexpr
, like this:
template <uint32_t DataLength, uint32_t ChunkSize, uint32_t Chunks>
int GetBitsToAppend() {
constexpr int BitsToAppend = ChunkSize*Chunks - DataLength - 1 - (ChunkSize / 8);
if constexpr (0 > BitsToAppend)
return GetBitsToAppend<DataLength, ChunkSize, Chunks+1>();
else
return BitsToAppend;
}
Upvotes: 0