簡體   English   中英

以一種在使用臨時調用時生成編譯器錯誤的方式重載方法

[英]Overload a method in a way that generates a compiler error when called with a temporary

也許這段代碼最能說明我的意圖:

#include <array>

template <size_t N>
void f(std::array<char, N> arr)
{
}

template <size_t N>
void f(std::array<char, N>&& arr)
{
    static_assert(false, "This function may not be called with a temporary.");
}

f()應為lvalues編譯,但不能為rvalues編譯。 此代碼適用於MSVC,但GCC會在static_assert上跳閘,即使永遠不會調用此重載。

所以我的問題有兩個方面:如何用現代C ++正確表達我的意圖,為什么編譯器會在一個“死”模板重載中評估static_assert ,這種重載永遠不會被實例化?

在線試用: https//godbolt.org/z/yJJn7_

一種選擇是刪除static_assert ,而是將該函數標記為已刪除。 然后,如果您使用右值調用它,您將收到一條錯誤消息,說明您正在嘗試使用已刪除的函數

template <size_t N>
void f(const std::array<char, N>& arr)
{

}

template <size_t N>
void f(const std::array<char, N>&& arr) = delete; // used const here just in case we get a const prvalue

int main()
{
    std::array<char, 3> foo{};
    f(foo);
    //f(std::array<char, 3>{}); // error
    return 0;
}

很簡單。

template <size_t N>
void f(const std::array<char, N>&& arr) = delete;

只使用一個引用非const對象的函數是可能的:

template<size_t N> void f(std::array<char, N>& arr);

不再需要重載。

這條規則由語言規范執行。 但是 Visual C ++編譯器有一個擴展,允許將rvalues傳遞給這樣的函數。

除了其他答案之外,我還要注意標准庫中有一個與OP想要的完全對應的例子 - std::addressof

template<class T>
constexpr T* addressof(T&) noexcept;

template<class T>
const T* addressof(const T&&) = delete;

暫無
暫無

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

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