簡體   English   中英

帶有 const 參數的模板 operator= 問題

[英]issue with template operator= with const parameter

這是在 c++ 中,使用 Visual Studio 2019(尚未嘗試其他編譯器)。 我想添加一個模板化的 operator= 方法。 如果參數是非常量,它工作正常。 但是如果參數是 const,即使我制作了一個帶有 const 參數的版本,它也不會被調用。 相反,它做一個簡單的淺拷貝。

如果我使用命名 function 而不是運算符,它會按預期工作。 類似地,如果它沒有被模板化,那么操作符會按預期被調用。 組合似乎是問題所在。

這是一個展示該問題的示例。

class CTest
{
public:
    int x{};

    CTest() = default;
    CTest(int value) : x(value) {}

    // non-const operator=
    template<class SrcType>void operator=(SrcType& src)
    {
        x = src.x;
    }

    // const operator=
    template<class SrcType>void operator=(const SrcType& src)
    {
        x = src.x;
    }
};

int main()
{
    CTest   nonConstSrc{ 3 };
    const CTest constSrc{ 5 };
    CTest result;
    result = nonConstSrc;   // correctly calls non-const operator=
    result = constSrc;      // ? shallow copy, not calling const operator=

    return 0;
}

任何想法如何讓它使用我重載的 function? 謝謝。

你的 const function 模板沒有被調用,因為編譯器默認生成默認的復制賦值運算符,它具有簽名operator=(const CTest&) 當編譯器必須在非模板 function 和模板一之間進行選擇時(當兩者具有相同的匹配時),前者是首選。 這就是為什么不調用您的模板化方法的原因。

為了幫助編譯器編譯到你想要的 select 版本,添加:

CTest& operator=(const volatile CTest&) = delete;

通過上面,你禁用正常的 operator=,這里的volatile很重要,沒有它編譯器會抱怨operator=被禁用。 通過添加volatile ,您只需使模板版本比volatile版本更匹配。

rest 不變:

 template<class SrcType> 
 void operator=(SrcType& src)
 {
     x = src.x;
     puts("boom1");
 }

 template<class SrcType>
 void operator=(const SrcType& src) {
     x = src.x;
     puts("boom2");
 }

演示

如果 class 沒有聲明復制賦值,編譯器將隱式生成一個。

您 class 沒有復制賦值運算符,它只有一個模板賦值運算符。

當使用const object 調用時,隱式聲明的賦值運算符在重載決議期間是更好的匹配。

這里的問題是我們不能刪除隱式聲明的賦值運算符,因為它會產生編譯器錯誤。 然而,我們可以編寫自己的賦值運算符來轉發到我們的模板。

#include <iostream>

class CTest
{
public:
    int x{};

    CTest() = default;
    CTest(int value) : x(value) {}


    CTest(const CTest& v) = delete;
    CTest& operator=(const CTest& v) {
        return operator=<CTest>(v);
    }

    // non-const operator=
    template<class SrcType>CTest& operator=(SrcType& src)
    {
        x = src.x;
        std::cout << "non-const\n";
        return *this;
    }

    template<class SrcType>CTest& operator=(const SrcType& src)
    {
        x = src.x;
        std::cout << "const\n";
        return *this;
    }
};

int main()
{
    CTest   nonConstSrc{ 3 };
    const CTest constSrc{ 5 };
    CTest result;
    result = nonConstSrc;   // correctly calls non-const operator=
    result = constSrc;      // calls copy-assignment and forwards to template

    return 0;
}

暫無
暫無

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

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