簡體   English   中英

引用模板類型的賦值運算符需要非常量重載

[英]Assignment operator to reference template type requires non-const overload

我正在努力解決復制分配操作員問題。 盡管我有一些想法(最后列出),但我無所適從。 這是一個問題,因為我使用的是第3方庫,其類無法控制。

假設您有一個帶有復制分配運算符的模板化容器。 此運算符接受具有不同模板的另一個容器,並嘗試static_cast其他類型。

template <class U>
vec2<T>& operator=(const vec2<U>& v) {
    x = static_cast<T>(v.x);
    y = static_cast<T>(v.y);
    return *this;
}

這對於簡單的分配是很好的,但是,當對T使用引用時,會出現有關const值類型的編譯錯誤。 如果添加另一個接受非const引用的重載,它將進行編譯並工作。

我做了一個簡單的例子,應該可以說明這個問題。

template <class T>
struct vec2 final {
    vec2(T x_, T y_)
            : x(x_)
            , y(y_) {
    }

    template <class U>
    vec2(const vec2<U>& v)
            : x(static_cast<T>(v.x))
            , y(static_cast<T>(v.y)) {
    }

    template <class U>
    vec2<T>& operator=(const vec2<U>& v) {
        if (this == &v)
            return *this;

        x = static_cast<T>(v.x);
        y = static_cast<T>(v.y);
        return *this;
    }

    // Fix :
    /*
    template <class U>
    vec2<T>& operator=(vec2<U>& v) {
        x = static_cast<T>(v.x);
        y = static_cast<T>(v.y);
        return *this;
    }
    */

    T x;
    T y;
};

以及我如何嘗試使用它:

int main(int, char**) {
    vec2<int> v0 = { 0, 0 };
    vec2<int> v1 = { 1, 1 };
    vec2<int&> test[] = { { v0.x, v0.y }, { v1.x, v1.y } };

    vec2<int> muh_vec2 = { 2, 2 };
    test[0] = muh_vec2;
    printf("{ %d, %d }\n", test[0].x, test[0].y);

    return 0;
}

最新的AppleClang將產生以下錯誤:

main4.cpp:18:7: error: binding value of type 'const int' to reference to type 'int'
      drops 'const' qualifier
                x = static_cast<T>(v.x);
                    ^              ~~~
main4.cpp:63:10: note: in instantiation of function template specialization 'vec2<int
      &>::operator=<int>' requested here
        test[0] = muh_vec2;
                ^

我從中了解到的是,編譯器以某種方式嘗試通過const值進行賦值。 但是,為什么並且有一個非侵入式的解決方案呢?

我在這里確實找到了類似的問題: 模板賦值運算符重載了奧秘

閱讀此問題后,我的結論是:可能是默認賦值運算符引起了該問題? 我仍然不明白為什么,但是:/

這是一個在線示例: https : //wandbox.org/permlink/Fc5CERb9voCTXHiN

template <class U>
vec2<T>& operator=(const vec2<U>& v)

在此方法中, v是右側const視圖的名稱。 如果Uint ,則vxconst int

如果Tint& ,則this->xint&

this->x = static_cast<int&>(v.x);

這顯然是非法的:您不能將const int靜態轉換為非const引用。

一般的解決方案基本上需要重建std::tuplestd::pair機械。 SFINAE可用於引導它。 但是總的來說,包含引用的結構和包含值的結構通常是完全不同的野獸。 為兩者使用一個模板是有問題的。

template <class T>
struct vec2 final {
  template<class Self,
    std::enable_if_t<std::is_same<std::decay_t<Self>, vec2>>{}, bool> =true
  >
  friend auto as_tuple( Self&& self ){
    return std::forward_as_tuple( std::forward<Self>(self).x, std::forward<Self>(self).y );
  }

那么我們可以進行SFINAE測試以確定as_tuple(LHS)=as_tuple(RHS)是否有效。

進行構造是另一個痛苦,因為LHS的元組類型需要先進行按摩,然后才能進行可構造性測試。


您編寫的代碼越通用,所需的工作就越多。 在編寫無限通用代碼之前,請考慮實際用例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM