簡體   English   中英

為什么在 C++17 中 std::pair 的異構“移動”構造函數的顯式性發生了變化?

[英]Why explicit-ness of std::pair's heterogeneous "move"-constructor changed in C++17?

請原諒令人費解的標題,並考慮以下代碼:

#include <memory>
#include <utility>

using X = std::unique_ptr<int>;

using A = std::pair<int, const X>;
using B = std::pair<int,       X>;

static_assert(std::is_constructible<A, B>::value, "(1)"); // Ok.
static_assert(std::is_convertible<B, A>::value, "(2)"); // Rejected by GCC and Clang, in C++14 and before.

static_assert(std::is_constructible<const X, X>::value, "(3)"); // Ok.
static_assert(std::is_convertible<X, const X>::value, "(4)"); // Ok.

簡而言之,來自 std::pair<int, std::unique_ptr<int>> 類型右值的std::pair<int, std::unique_ptr<int>> std::pair<int, const std::unique_ptr<int>>的構造函數在 C++14 中是explicit的,和隱式和 C++17 及更高版本。 這種差異從何而來?

只有 libstdc++ 和 libc++ 展示了這種行為。 在 MSVC 的庫中,構造函數始終是隱式的。

為什么它在 C++14 中是explicit的? 我沒有看到任何與cppreference相關的內容(構造函數 (6))。

相關的構造函數在 C++17 之前也沒有explicit

pre-C++17 模式下的 GCC 和 Clang 實際上正在考慮std::is_convertible<B, A>::value false 因為A的移動構造函數被隱式刪除。

移動構造函數被隱式刪除,因為const std::unique_ptr不能被移動或復制。

在 C++17 之前,移動構造函數需要滿足std::is_convertible<B, A>::value ,因為它測試是否有以下形式的函數

A test() {
    return std::declval<B>();
}

會形成良好的。 return 語句從操作數復制初始化A返回值,在 C++17 復制初始化之前,如有必要,復制初始化始終涉及轉換為目標類型的臨時對象,然后從臨時對象直接初始化目標。 該直接初始化將使用A的移動構造函數。 編譯器可以忽略移動,但移動構造函數必須仍然可用。

由於 C++17 強制復制省略適用,甚至在概念上,復制初始化不再包含通過移動構造函數進行的直接初始化。

暫無
暫無

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

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