簡體   English   中英

使用統一初始化語法從函數返回元組

[英]Returning a tuple from a function using uniform initialization syntax

以下代碼使用clang(libc ++)編譯,並使用gcc(libstdc ++)失敗。 為什么gcc(libstdc ++)抱怨初始化列表? 我認為return參數使用統一初始化語法。

std::tuple<double,double> dummy() {
  return {2.0, 3.0};
}

int main() {   
  std::tuple<double,double> a = dummy();   
  return 0;
}

錯誤:第22行:從initializer \\ list轉換為'std :: tuple'將使用顯式構造函數'constexpr std :: tuple <_T1,_T2> :: tuple(_U1&\\&,_ U2 &&)[with _U1 = double; _U2 =雙倍; =無效 _T \\ 1 =雙倍; _T2 =雙倍]'

注意: GCC(libstdc ++)(和clang(libc ++))接受

std::tuple<double,double> dummy {1.0, 2.0};

是不是一樣的情況?

更新:這是一個libc ++擴展,請參閱http://llvm.org/bugs/show_bug.cgi?id=15299 ,並由Howard Hinnant在下面回答。

pair<>不同,不幸的是,不可能隱式構造tuple<> 你必須使用make_tuple()

#include <tuple>

std::tuple<double,double> dummy()
{
    return std::make_tuple(2.0, 3.0); // OK
}

int main() 
{   
    std::tuple<double,double> a = dummy();   
    return 0;
}

std::tuple有一個可變參數構造函數,但它被標記為explicit 因此,它不能用於這種情況,其中臨時必須是可隱式構造的。 根據C ++ 11標准的第20.4.2段:

namespace std {
    template <class... Types>
    class tuple {
    public:

        [...]
        explicit tuple(const Types&...); // Marked as explicit!

        template <class... UTypes>
        explicit tuple(UTypes&&...);     // Marked as explicit!

出於同樣的原因,使用復制初始化語法初始化元組是非法的:

std::tuple<double, double> a = {1.0, 2.0}; // ERROR!
std::tuple<double, double> a{1.0, 2.0}; // OK

或者在將其作為參數傳遞給函數時隱式構造元組:

void f(std::tuple<double, double> t) { ... }
...
f({1.0, 2.0}); // ERROR!
f(make_tuple(1.0, 2.0)); // OK

因此,如果在dummy()返回它時顯式構造std::tuple ,則不會發生編譯錯誤:

#include <tuple>

std::tuple<double,double> dummy()
{
    return std::tuple<double, double>{2.0, 3.0}; // OK
}

int main() 
{   
    std::tuple<double,double> a = dummy();   
    return 0;
}

Andy Prowl給出的答案是正確的。 我想對libc ++實現發表評論,而評論格式不允許我有足夠的空間或格式選擇。

DanielKrügler和我在一年前就這個問題進行了一次對話,他讓我相信這個問題值得對libc ++進行擴展以獲得實地經驗。 到目前為止,反饋都是積極的。 但是我想說清楚:這並不像從ctor explicit constexpr tuple(UTypes&&...)刪除explicit那樣簡單explicit constexpr tuple(UTypes&&...)

Daniel的計划是給tuple一個完美地尊重每個元素的隱式/顯式構造的構造函數。 如果每個元素都將從初始化列表中的每個參數隱式構造, 那么元組構造是隱式的,否則它將是顯式的。

例如:

鑒於:

#include <tuple>

struct A
{
};

struct B
{
    B() = default;
    B(A);
};

struct C
{
    C() = default;
    explicit C(A);
};

然后:

std::tuple<>
test0()
{
    return {};  // ok
}

關於那個沒什么可說的。 但這也沒關系:

std::tuple<B>
test1B()
{
    return {A()};  // ok B(A) implicit
}

因為從AB的轉換是隱含的。 但是以下是編譯時錯誤:

std::tuple<C>
test1C()
{
    return {A()};  // error, C(A) is explicit
}

因為從AC的轉換是明確的。 這種邏輯繼續用於多元素元組。 要進行隱式轉換,每個元素必須從參數列表中進行隱式轉換:

std::tuple<A, B>
test2B()
{
    return {A(), A()};  // ok each element has implicit ctor
}

std::tuple<A, C>
test2C()
{
    return {A(), A()};  // error, C(A) is explicit
}

我應該強調:這是一個libc ++擴展。

更新

chico提出了一個很好的建議,我更新了這個答案:

自從給出了這個答案后,DanielKrügler寫了一篇論文,並於今年4月將其提交給布里斯托爾的C ++委員會。 雖然該文件很受歡迎,但本周審查得太晚,無法將其投入當前的工作草案。

更新

丹尼爾的提議現在已成為當前工作草案的一部分 現在,libc ++實現已成為下一個C ++標准(我們希望的C ++ 17)的標准。

暫無
暫無

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

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