1

This was much longer, but now that I found what was going on it was not helpful.

Short summary:

  1. Template with variable ints summing < 64.
  2. We want to know the # of ints + how many times the last int has to be repeated to reach a sum >= 64.
  3. 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
4
  • 6
    TL;DR! Please narrow the code down to a minimal example. Commented Sep 10, 2014 at 6:39
  • Also, when you say that "Clang crashes", what do you mean by that? Do you get e.g. a segmentation fault or similar from the compiler? What messages (error, warnings or others) do you get? Which version of the compiler? Please elaborate! Commented Sep 10, 2014 at 6:41
  • Compiles fine on clang 3.5 (Assuming the static member definition is uncommented and fixed to match the declaration). Commented Sep 10, 2014 at 6:52
  • 1
    @Asher It wouldn't compile unless the array size was specified with BitBranchTree::numberOfBranches. clang-503.0.40 is based on 3.4 so this could be a compiler bug. Commented Sep 10, 2014 at 7:04

1 Answer 1

2

You need to match the definition of BitBranchTree::branches with the declaration as follows

template
<class          BitBranch,
 uint64_t...    BitLengths>
constexpr const std::array <BitBranch, BitBranchTree<BitBranch, BitLengths...>::numberOfBranches>
BitBranchTree<BitBranch, BitLengths...>::branches;

You could also change the declaration to use branchCount(), the important thing is that they are identical.

Presumably clang 3.4 crashed instead of giving an error due to a compiler bug, your original code gives the following error on clang 3.5

test.cpp:199:42: error: redefinition of 'branches' with a different type: 'array<[...], BitBranchTree<BitBranch, BitLengths...>::branchCount()>' vs
      'const array<[...], numberOfBranches>'
BitBranchTree<BitBranch, BitLengths...>::branches;
                                         ^
test.cpp:181:7: note: previous definition is here
      branches = initializeBranches( std::make_integer_sequence <uint64_t, numberOfBranches>{} );
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.