[英]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.