This was much longer, but now that I found what was going on it was not helpful.
Short summary:
- Template with variable ints summing < 64.
- We want to know the # of ints + how many times the last int has to be repeated to reach a sum >= 64.
- We want to end up with a constexpr const static array std::array.
I was having linking errors without a declaration of the static member outside of the class. When present, Clang was segfaulting.
The problem ended up being that I had defined the function as
<BitBranch, numberOfBranches>
but then the declaration had ended up using the numberOfBranches accessor method
<BitBranch, branchCount()>
A very silly mistake, but it wasn't obvious to me to track down.
I'll include my code as an example in case someone finds it helpful.
Working with C++14:
/* Using -std=c++1y */
#include <array>
#include <cmath>
template
<class BitBranch,
uint64_t... BitLengths>
class BitBranchTree
{
Count How Many Bits are covered by Explicit Parameters in Pack
template <typename ...Ints>
constexpr static uint64_t countExplicitBits(
uint64_t bit_length,
Ints... bit_lengths )
{
return bit_length + countExplicitBits( bit_lengths... );
}
constexpr static uint64_t countExplicitBits(
uint64_t bit_length )
{
return bit_length;
}
Count How Many Bits Require Additional Implicit Parameters
constexpr
static
uint64_t
calculateImplicitBranches()
{
uint64_t remaining_bits = 64 - explicitBitCount;
uint64_t final_explicit_bit_length = explicitBranchLengths[ explicitBranchCount - 1 ];
uint64_t smaller_final_length = remaining_bits % final_explicit_bit_length;
uint64_t remaining_full_branches = remaining_bits / final_explicit_bit_length;
uint64_t implicit_branch_count = smaller_final_length ? remaining_full_branches + 1
: remaining_full_branches;
return implicit_branch_count;
}
Initialize Desired Final Array
template <uint64_t... Indexes>
constexpr static std::array<BitBranch, sizeof...(Indexes)>
initializeBranches(
std::integer_sequence<uint64_t, Indexes...> )
{
return { initializeBranch( Indexes )... };
}
Initialize Each Branch of Final Array
constexpr static BitBranch
initializeBranch(
uint64_t index )
{
uint64_t bit_length = ( index < explicitBranchCount )
? explicitBranchLengths[ index ]
: explicitBranchLengths[ explicitBranchCount - 1 ];
return BitBranch( bit_length );
}
Member Variables / Initialization
constexpr static const uint64_t
explicitBranchCount = sizeof...(BitLengths);
constexpr static const uint64_t
explicitBitCount = countExplicitBits( BitLengths... );
constexpr static const uint64_t
explicitBranchLengths[ explicitBranchCount ] = { BitLengths... };
constexpr static const uint64_t
implicitBranchCount = calculateImplicitBranches();
static const uint64_t
numberOfBranches = explicitBranchCount + implicitBranchCount;
constexpr static const std::array <BitBranch, numberOfBranches>
branches = initializeBranches( std::make_integer_sequence <uint64_t, numberOfBranches>{} );
};
Finally, Outside of the Class
template
<class BitBranch,
uint64_t... BitLengths>
constexpr
const
std::array
<BitBranch,
BitBranchTree<BitBranch, BitLengths...>::numberOfBranches>
BitBranchTree<BitBranch, BitLengths...>::branches;
Examples of Usage
typedef
BitBranchTree<BitBranchMock, 4, 16, 7, 8, 5, 2, 8, 12, 2>
CompleteSpecification; // Results in Branches: 4, 16, 7, 8, 5, 2, 8, 12, 2
typedef
BitBranchTree<BitBranchMock, 4, 16>
PartialSpecification; // Results in Branches: 4, 16, 16, 16, 12
BitBranchTree::numberOfBranches. clang-503.0.40 is based on 3.4 so this could be a compiler bug.