[英]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
}
因為從A
到B
的轉換是隱含的。 但是以下是編譯時錯誤:
std::tuple<C>
test1C()
{
return {A()}; // error, C(A) is explicit
}
因為從A
到C
的轉換是明確的。 這種邏輯繼續用於多元素元組。 要進行隱式轉換,每個元素必須從參數列表中進行隱式轉換:
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.