diff --git a/include/hglib/hyperedge/HyperedgeBase.h b/include/hglib/hyperedge/HyperedgeBase.h
index 774cb859013f6da54595c4d3332a5a079cead7e8..733bb8b6e369e9dedd500ec4e8ac8a0bd4e3fae3 100644
--- a/include/hglib/hyperedge/HyperedgeBase.h
+++ b/include/hglib/hyperedge/HyperedgeBase.h
@@ -20,26 +20,63 @@
 
 namespace hglib {
 
+template <typename Hyperedge_t>
+typename Hyperedge_t::SpecificAttributes
+specificAttributes(const Hyperedge_t& hyperedge);
+
 /**
  * \brief Base class for all hyperedges
  */
 class HyperedgeBase {
  public:
+  /**
+   * \brief SpecificAttributes nested class
+   *
+   * \details
+   * The nested class SpecificAttributes allows classes derived from
+   * HyperedgeBase to specify additional attributes in a packed and
+   * unified way.
+   */
+  class SpecificAttributes {};
+
   /// Constructor
   HyperedgeBase(HyperedgeIdType id) : id_(id) {}
   /// Copy constructor
-  HyperedgeBase(const HyperedgeBase&) = default;
+  HyperedgeBase(const HyperedgeBase& other) : id_(other.id_) {
+    specific_attributes_ =
+        std::make_unique<SpecificAttributes>(specificAttributes(other));
+  }
 
   /// Get the identifier
   const auto id() const { return id_; }
+  /// Get the specific attributes
+  const auto& specific_attributes() const { return *specific_attributes_; }
 
  protected:
-  /// Unique identifier
-  HyperedgeIdType id_;
   /// Assign new identifier
   void setId(const HyperedgeIdType& id) { id_ = id; }
+
+  /// Unique identifier
+  HyperedgeIdType id_;
+  /// Specific attributes
+  std::unique_ptr<SpecificAttributes> specific_attributes_;
 };
 
+/**
+ * Get the specific attributes of hyperedge in its specific type
+ *
+ * \tparam Hyperedge_t enclosing class for SpecificAttributes
+ * \param hyperedge hyperedge which specific attributes are to be returned
+ * \return hyperedge's specific attributes casted to
+ * const Hyperedge_t::SpecificAttributes
+ */
+template <typename Hyperedge_t>
+typename Hyperedge_t::SpecificAttributes
+specificAttributes(const Hyperedge_t& hyperedge) {
+  return static_cast<const typename Hyperedge_t::SpecificAttributes&>(
+      hyperedge.specific_attributes());
+}
+
 }  // namespace hglib
 
 #endif  // HGLIB_HYPEREDGEBASE_H
diff --git a/include/hglib/hyperedge/directed/DirectedHyperedgeBase.h b/include/hglib/hyperedge/directed/DirectedHyperedgeBase.h
index 2800cd8686af90fcc75e339a582ffb15effffd8a..fafaa2f202a8e7dc4c6fe0be15b08c508335993c 100644
--- a/include/hglib/hyperedge/directed/DirectedHyperedgeBase.h
+++ b/include/hglib/hyperedge/directed/DirectedHyperedgeBase.h
@@ -84,17 +84,6 @@ class DirectedHyperedgeBase : public HyperedgeBase {
           typename HypergraphProperty>
   friend class DirectedSubHypergraph;
 
- public:
-  /**
-   * \brief SpecificAttributes nested class
-   *
-   * \details
-   * The nested class SpecificAttributes allows classes derived from
-   * DirectedHyperedgeBase to specify additional attributes in a packed and
-   * unified way.
-   */
-  class SpecificAttributes {};
-
  protected:
   /// DirectedHyperedgeBase constructor
   DirectedHyperedgeBase(HyperedgeIdType id,
@@ -105,8 +94,6 @@ class DirectedHyperedgeBase : public HyperedgeBase {
   DirectedHyperedgeBase(const DirectedHyperedgeBase& hyperarc);
 
  public:
-  /// Get the specific attributes
-  const auto& specific_attributes() const { return *specific_attributes_; }
   /// Print the directed hyperedge
   void print(std::ostream& out) const;
 
@@ -130,8 +117,6 @@ class DirectedHyperedgeBase : public HyperedgeBase {
   std::shared_ptr<GraphElementContainer<DirectedVertex_t*>> tails_;
   /// Head vertices of the hyperarc
   std::shared_ptr<GraphElementContainer<DirectedVertex_t*>> heads_;
-  /// Specific attributes
-  std::unique_ptr<SpecificAttributes> specific_attributes_;
 };
 
 template <typename DirectedVertex_t>
@@ -142,21 +127,6 @@ std::ostream& operator<< (
   return out;
 }
 
-/**
- * Get the specific attributes of hyperedge in its "final" type
- *
- * \tparam Hyperedge_t enclosing class for SpecificAttributes
- * \param hyperedge hyperedge which specific attributes are to be returned
- * \return hyperedge's specific attributes casted to
- * const Hyperedge_t::SpecificAttributes
- */
-template <typename Hyperedge_t>
-typename Hyperedge_t::SpecificAttributes
-specificAttributes__(const Hyperedge_t& hyperedge) {
-  return static_cast<const typename Hyperedge_t::SpecificAttributes&>(
-      hyperedge.specific_attributes());
-}
-
 }  // namespace hglib
 
 #include "DirectedHyperedgeBase.hpp"
diff --git a/include/hglib/hyperedge/directed/NamedDirectedHyperedge.h b/include/hglib/hyperedge/directed/NamedDirectedHyperedge.h
index 9032709aeaafb76756444867f6eeea065e8b5f60..2050b67902859f3bc09f3a232d97987a8f7a5f6c 100644
--- a/include/hglib/hyperedge/directed/NamedDirectedHyperedge.h
+++ b/include/hglib/hyperedge/directed/NamedDirectedHyperedge.h
@@ -92,16 +92,15 @@ class NamedDirectedHyperedge final :
    * **************************************************************************
    ***************************************************************************/
  public:
-/**
- * \brief SpecificAttributes nested class
- *
- * \details
- * The nested class SpecificAttributes allows classes derived from
- * DirectedHyperedgeBase to specify additional attributes in a packed and
- * unified way.
- */
-  class SpecificAttributes :
-      public DirectedHyperedgeBase::SpecificAttributes {
+  /**
+   * \brief SpecificAttributes nested class
+   *
+   * \details
+   * The nested class SpecificAttributes allows classes derived from
+   * HyperedgeBase to specify additional attributes in a packed and
+   * unified way.
+   */
+  class SpecificAttributes : public DirectedHyperedgeBase::SpecificAttributes {
    public:
     /// SpecificAttributes constructor
     SpecificAttributes(const std::string& name) : name_(name) {}
@@ -163,7 +162,7 @@ class NamedDirectedHyperedge final :
  * \return std::string Name of the directed hyperedge.
  */
 std::string NamedDirectedHyperedge::name() const {
-  return specificAttributes__(*this).name_;
+  return specificAttributes(*this).name_;
 }
 
 }  // namespace hglib
diff --git a/include/hglib/hyperedge/undirected/NamedUndirectedHyperedge.h b/include/hglib/hyperedge/undirected/NamedUndirectedHyperedge.h
index b5cac81ad93eea2f25c61f98f3560a63700d793b..efd360cbed3909f5dc727f915cdb8e077b1c23e4 100644
--- a/include/hglib/hyperedge/undirected/NamedUndirectedHyperedge.h
+++ b/include/hglib/hyperedge/undirected/NamedUndirectedHyperedge.h
@@ -94,7 +94,7 @@ class NamedUndirectedHyperedge final :
    *
    * \details
    * The nested class SpecificAttributes allows classes derived from
-   * UndirectedHyperedgeBase to specify additional attributes in a packed and
+   * HyperedgeBase to specify additional attributes in a packed and
    * unified way.
    */
   class SpecificAttributes :
diff --git a/include/hglib/hyperedge/undirected/UndirectedHyperedgeBase.h b/include/hglib/hyperedge/undirected/UndirectedHyperedgeBase.h
index f3c16603496722ed8b2fd2cb0edc55650ba4effe..537ec916f0e764797f562e4cc1fd6de620f0b5ca 100644
--- a/include/hglib/hyperedge/undirected/UndirectedHyperedgeBase.h
+++ b/include/hglib/hyperedge/undirected/UndirectedHyperedgeBase.h
@@ -78,17 +78,6 @@ class UndirectedHyperedgeBase : public HyperedgeBase {
           typename HypergraphProperty>
   friend class UndirectedSubHypergraph;
 
- public:
-  /**
-   * \brief SpecificAttributes nested class
-   *
-   * \details
-   * The nested class SpecificAttributes allows classes derived from
-   * UndirectedHyperedgeBase to specify additional attributes in a packed and
-   * unified way.
-   */
-  class SpecificAttributes {};
-
  protected:
   /// UndirectedHyperedgeBase constructor
   UndirectedHyperedgeBase(
@@ -99,8 +88,6 @@ class UndirectedHyperedgeBase : public HyperedgeBase {
   UndirectedHyperedgeBase(const UndirectedHyperedgeBase& other);
 
  public:
-  /// Get the specific attributes
-  const auto& specific_attributes() const { return *specific_attributes_; }
   /// Print the undirected hyperedge
   void print(std::ostream& out) const;
 
@@ -117,8 +104,6 @@ class UndirectedHyperedgeBase : public HyperedgeBase {
  protected:
   /// Vertices of the undirected hyperedge
   std::shared_ptr<GraphElementContainer<UndirectedVertex_t*>> vertices_;
-  /// Specific attributes
-  std::unique_ptr<SpecificAttributes> specific_attributes_;
 };
 
 /**
@@ -141,21 +126,6 @@ std::ostream& operator<< (
   return out;
 }
 
-/**
- * Get the specific attributes of hyperedge in its "final" type
- *
- * \tparam Hyperedge_t enclosing class for SpecificAttributes
- * \param hyperedge hyperedge which specific attributes are to be returned
- * \return hyperedge's specific attributes casted to
- * const Hyperedge_t::SpecificAttributes
- */
-template <typename Hyperedge_t>
-typename Hyperedge_t::SpecificAttributes
-specificAttributes(const Hyperedge_t& hyperedge) {
-  return static_cast<const typename Hyperedge_t::SpecificAttributes&>(
-      hyperedge.specific_attributes());
-}
-
 }  // namespace hglib
 
 #include "UndirectedHyperedgeBase.hpp"
diff --git a/src/hyperedge/directed/DirectedHyperedge.cpp b/src/hyperedge/directed/DirectedHyperedge.cpp
index 9438e8aff349d092354774d1e6344bd8ed01c223..df383363cef638c3acd819141f0cac432a8ec318 100644
--- a/src/hyperedge/directed/DirectedHyperedge.cpp
+++ b/src/hyperedge/directed/DirectedHyperedge.cpp
@@ -85,7 +85,7 @@ argumentsToCreateHyperarc() const {
   }
   return ArgumentsToCreateDirectedHyperedge<DirectedHyperedge>(
           std::make_pair(tails, heads),
-          specificAttributes__(*this));
+          specificAttributes(*this));
 }
 
 /**
diff --git a/src/hyperedge/directed/NamedDirectedHyperedge.cpp b/src/hyperedge/directed/NamedDirectedHyperedge.cpp
index 4b9f0cfe71bee232b31f65121569ccbc80f138b9..604a10450b338b653a3a7aeb1066fbe820df11a9 100644
--- a/src/hyperedge/directed/NamedDirectedHyperedge.cpp
+++ b/src/hyperedge/directed/NamedDirectedHyperedge.cpp
@@ -50,7 +50,7 @@ NamedDirectedHyperedge::
 NamedDirectedHyperedge(const NamedDirectedHyperedge& other) :
         DirectedHyperedgeBase(other) {
   specific_attributes_ =
-      std::make_unique<SpecificAttributes>(specificAttributes__(other));
+      std::make_unique<SpecificAttributes>(specificAttributes(other));
 }
 
 
@@ -97,7 +97,7 @@ argumentsToCreateHyperarc() const {
     heads.push_back(vertex->id());
   }
   return ArgumentsToCreateDirectedHyperedge<NamedDirectedHyperedge>(
-          std::make_pair(tails, heads), specificAttributes__(*this));
+          std::make_pair(tails, heads), specificAttributes(*this));
 }