代码之家  ›  专栏  ›  技术社区  ›  TomáÅ¡ Zato

我的variadric模板化构造函数隐藏复制构造函数,防止类被复制

  •  0
  • TomáÅ¡ Zato  · 技术社区  · 3 年前

    我做了一个 Vector<numType, numberOfCoords> 班我对此很满意,这有点奇怪,但一开始似乎奏效了。但我刚刚发现复制矢量是不可能的。

    原因是为了允许坐标的数量成为模板,有一个模板化的可变构造函数,它需要正确的坐标数量。

    这就是它的样子,去掉了实用数学方法:

    template <typename NumType, unsigned char Size>
    class Vector
    {
    public:
      using CoordType = NumType;
    
      //Vector(const Vector& v) : values(v.values) {}
      //Vector(Vector&& v) : values(std::move(v.values)) {}
    
      template<typename... NumTypes>
      constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... }
      {
        static_assert(sizeof...(NumTypes) == Size, "You must provide N arguments.");
      }
    
      Vector(const std::array<NumType, Size>& values) : values(values) {}
      Vector(std::array<NumType, Size>&& values) : values(std::move(values)) {}
    
      const NumType& operator[](size_t offset) const { return values[offset]; }
      NumType& operator[](size_t offset) { return values[offset]; }
      //Vector& operator=(const Vector& other) { values = other.values; }
      //Vector& operator=(Vector&& other) { values = std::move(other.values); }
    
      std::array<NumType, Size> values;
    
    };
    

    正如您所看到的——现在已经注释掉了——我确实尝试手动实现复制、移动和分配操作。它没有任何影响,错误总是沿着以下路线:

    cannot convert ‘Vector<int, 3>’ to ‘int’ in initialization
    

    这是因为它仍在尝试使用可变构造函数,而不是复制构造函数。

    这是满的 工作 破碎样品: https://ideone.com/Jz86vP

    0 回复  |  直到 3 年前
        1
  •  3
  •   Jarod42    3 年前

    您可能会:

    • SFINAE您的可变构造函数,例如:

      template <typename... NumTypes,
                std::enable_if_t<sizeof...(NumTypes) == Size
                             && std::conjunction<std::is_same<NumType, NumTypes>::value,
                                int> = 0>
      constexpr Vector(NumTypes&&... vals) : values{ std::forward<NumTypes>(vals)... }
      {
      }
      

      笔记 std::conjunction 是C++17,但可以在C++14中完成。

    • 或在标签前加上:

      template <typename... NumTypes>
      constexpr Vector(struct SomeTag, NumTypes&&... vals) :
          values{ std::forward<NumTypes>(vals)... }
      {
      }
      
    • 或者重新设计类,例如:

      template <typename T, std::size_t>
      using always_type = T;
      
      template <typename NumType, typename Seq> class VectorImpl;
      
      template <typename NumType, std::size_t ... Is>
      class VectorImpl<NumType, std::index_sequence<Is...>>
      {
      public:
        using CoordType = NumType;
      
        VectorImpl(const VectorImpl&) = default;
        VectorImpl(VectorImpl&&) = default;
        VectorImpl& operator=(const VectorImpl&) = default;
        VectorImpl& operator=(VectorImpl&&) = default;
      
        constexpr VectorImpl(always_type<NumType, Is>... vals) : values{ std::forward<NumType>(vals)... }
        {
        }
      
        VectorImpl(const std::array<NumType, sizeof...(Is)>& values) : values(values) {}
        VectorImpl(std::array<NumType, sizeof...(Is)>&& values) : values(std::move(values)) {}
      
        const NumType& operator[](size_t offset) const { return values[offset]; }
        NumType& operator[](size_t offset) { return values[offset]; }
      
        std::array<NumType, sizeof...(Is)> values;
      };
      
      template <typename T, std::size_t N>
      using Vector = VectorImpl<T, std::make_index_sequence<N>>;
      

      Demo