<commit_before>#ifndef _SDD_DD_NODE_HH_
#define _SDD_DD_NODE_HH_

#include <algorithm>  // equal, for_each
#include <functional> // hash
#include <iosfwd>

#include "sdd/dd/alpha.hh"
#include "sdd/dd/definition.hh"
#include "sdd/util/hash.hh"
#include "sdd/util/packed.hh"

namespace sdd {

/*------------------------------------------------------------------------------------------------*/

/// @brief  A non-terminal node in an SDD.
/// \tparam Valuation If a set of values, define a flat node; if an SDD, define a hierarchical
/// node.
///
/// For the sake of canonicity, a node shall not exist in several locations, thus we prevent
/// its copy. Also, to enforce this canonicity, we need that nodes have always the same
/// address, thus they can't be moved to an other memory location once created.
template <typename C, typename Valuation>
class LIBSDD_ATTRIBUTE_PACKED node final
{
  // Can't copy a node.
  node& operator=(const node&) = delete;
  node(const node&) = delete;  

  // Can't move a node.
  node& operator=(node&&) = delete;
  node(node&&) = delete;

public:

  /// @brief The type of the variable of this node.
  typedef typename C::Variable variable_type;

  /// @brief The type of the valuation of this node.
  typedef Valuation valuation_type;

  /// @brief The type used to store the number of arcs of this node.
  typedef typename C::alpha_size_type alpha_size_type;

  /// @brief A (const) iterator on the arcs of this node.
  typedef const arc<C, Valuation>* const_iterator;

private:

  /// @brief The variable of this node.
  const variable_type variable_;

  /// @brief The number of arcs of this node.
  const alpha_size_type size_;

public:

  /// @internal
  /// @brief Constructor.
  ///
  /// O(n) where n is the number of arcs in the builder.
  /// It can't throw as the memory for the alpha has already been allocated.
  node(const variable_type& var, dd::alpha_builder<C, Valuation>& builder)
  noexcept
    : variable_(var)
    , size_(static_cast<alpha_size_type>(builder.size()))
  {
    // Instruct the alpha builder to place it right after the node.
    builder.consolidate(alpha_addr());
  }

  /// @internal
  /// @brief Destructor.
  ///
  /// O(n) where n is the number of arcs in the node.
  ~node()
  {
    for (auto& a : *this)
    {
      a.~arc<C, Valuation>();
    }
  }

  /// @brief Get the variable of this node.
  ///
  /// O(1).
  const variable_type&
  variable()
  const noexcept
  {
    return variable_;
  }

  /// @brief Get the beginning of arcs.
  ///
  /// O(1).
  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const arc<C, Valuation>*>(alpha_addr());
  }

  /// @brief Get the end of arcs.
  ///<commit_msg>Don't return a const& when getting a node's variable: it's always an integral_type.<commit_after>#ifndef _SDD_DD_NODE_HH_
#define _SDD_DD_NODE_HH_

#include <algorithm>  // equal, for_each
#include <functional> // hash
#include <iosfwd>

#include "sdd/dd/alpha.hh"
#include "sdd/dd/definition.hh"
#include "sdd/util/hash.hh"
#include "sdd/util/packed.hh"

namespace sdd {

/*------------------------------------------------------------------------------------------------*/

/// @brief  A non-terminal node in an SDD.
/// \tparam Valuation If a set of values, define a flat node; if an SDD, define a hierarchical
/// node.
///
/// For the sake of canonicity, a node shall not exist in several locations, thus we prevent
/// its copy. Also, to enforce this canonicity, we need that nodes have always the same
/// address, thus they can't be moved to an other memory location once created.
template <typename C, typename Valuation>
class LIBSDD_ATTRIBUTE_PACKED node final
{
  // Can't copy a node.
  node& operator=(const node&) = delete;
  node(const node&) = delete;  

  // Can't move a node.
  node& operator=(node&&) = delete;
  node(node&&) = delete;

public:

  /// @brief The type of the variable of this node.
  typedef typename C::Variable variable_type;

  /// @brief The type of the valuation of this node.
  typedef Valuation valuation_type;

  /// @brief The type used to store the number of arcs of this node.
  typedef typename C::alpha_size_type alpha_size_type;

  /// @brief A (const) iterator on the arcs of this node.
  typedef const arc<C, Valuation>* const_iterator;

private:

  /// @brief The variable of this node.
  const variable_type variable_;

  /// @brief The number of arcs of this node.
  const alpha_size_type size_;

public:

  /// @internal
  /// @brief Constructor.
  ///
  /// O(n) where n is the number of arcs in the builder.
  /// It can't throw as the memory for the alpha has already been allocated.
  node(const variable_type& var, dd::alpha_builder<C, Valuation>& builder)
  noexcept
    : variable_(var)
    , size_(static_cast<alpha_size_type>(builder.size()))
  {
    // Instruct the alpha builder to place it right after the node.
    builder.consolidate(alpha_addr());
  }

  /// @internal
  /// @brief Destructor.
  ///
  /// O(n) where n is the number of arcs in the node.
  ~node()
  {
    for (auto& a : *this)
    {
      a.~arc<C, Valuation>();
    }
  }

  /// @brief Get the variable of this node.
  ///
  /// O(1).
  variable_type
  variable()
  const noexcept
  {
    return variable_;
  }

  /// @brief Get the beginning of arcs.
  ///
  /// O(1).
  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const arc<C, Valuation>*>(alpha_addr());
  }

  /// @brief Get the end of arcs.
  ///
{'fraction_non_alphanumeric': 0.15428154098959285, 'fraction_numerical': 0.0007303268212525105, 'mean_word_length': 2.5364751452550034, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1147412', 'n_tokens_mistral': 1761, 'n_tokens_neox': 1693, 'n_words': 623}