Std :: swap neden Clang / Win altındaki vektör <bool> öğeleri üzerinde çalışmıyor?


14

Ben böyle bir kod var:

#include <vector>
#include <utility>

int main()
{
   std::vector<bool> vb{true, false};
   std::swap(vb[0], vb[1]);
}

Bir vector<bool>yana akıl sağlığı ile ilgili tartışmalar, bu iyi çalışıyor:

  • Mac için Clang
  • Windows için Visual Studio
  • Linux için GCC

Sonra Windows üzerinde Clang ile inşa etmeyi denedim ve aşağıdaki hatayı aldım (kısaltılmış):

error: no matching function for call to 'swap'
                                std::swap(vb[0], vb[1]);
                                ^~~~~~~~~

note: candidate function [with _Ty = std::_Vb_reference<std::_Wrap_alloc<std::allocator<unsigned int> > >, $1 = void] not viable: expects an l-value for 1st argument
inline void swap(_Ty& _Left, _Ty& _Right) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty>&&

Sonuçların uygulamalar arasında farklılık göstermesine şaşırdım.

Windows'ta Clang ile neden çalışmıyor?


Sanırım gereken açıklama şudur: operator[]Bir değerin sonucu mu? ve std::swapdeğerlerde ve x değerlerinde çalışabilir mi?
Mgetz

@Mgetz Evet. Hayır. Bu soru geçen gün özel olarak "gerçek" için sorulmuştu ve cevabın "Clang / Win kırık değil; kodun tüm zaman kırılmış olmasına rağmen yeterince eğlenceli olduğunu düşündüm ama ana araç zinciri kombinasyonları size söylemek için hiç uğraşmadı "buraya yazmak için: P
Orbit'teki Hafiflik Yarışları

2
Tıpkı bir FYI gibi, bu VS 2019'da /permissive-genellikle yine de kullanılması gereken (uygunluk) ile derlenmez ;)
ChrisMM

1
@ChrisMM Gerçekten! Uyumluluk modu kapalı bulmacanın bir parçasıydı. (Buna bakmadan bilmesek de!) Ve cevabım şunu gösteriyor: P
Orbit'teki Hafiflik Yarışları

Yanıtlar:


15

Standart bunun herhangi bir alet zincirinde derlenmesini gerektirmez !

vector<bool>Garip ve abone olmak ilk hatırlama size std::vector<bool>::referencegerçek yerine bir proxy türünde geçici bir nesne verir bool&.

Hata iletisi, bu geçici uygulamayı constgenel template <typename T> std::swap(T& lhs, T& rhs)uygulamadaki bir değer içermeyen başvuruyla ilişkilendiremeyeceğini söylüyor .

Uzantıları!

Ancak, libstdc ++ için bir aşırı yük tanımladığı ortaya çıkıyor std::swap(std::vector<bool>::reference, std::vector<bool>::reference), ancak bu standardın bir uzantısı (veya oradaysa, bunun için herhangi bir kanıt bulamıyorum).

libc ++ bunu da yapar .

Hala kullandığınız Visual Studio stdlib uygulamasının işe yaramadığını tahmin ediyorum , ancak daha sonra yaralanmaya hakaret eklemek için geçici geçişleri VS'de (uyumluluk modunu kullanmıyorsanız) lvalue referanslarına bağlayabilirsiniz . standart "generic" std::swapişlevi, daha katı Clang derleyicisinin VS derleyicisini değiştirene kadar çalışır.

Sonuç olarak, sizin için çalıştığı üç araç zincirinin tamamındaki uzantılara güveniyorsunuz ve Windows'ta Clang kombinasyonu gerçekten sıkı uyum gösteren tek.

(Bence, bu üç araç zinciri bunu teşhis etmeliydi, bu yüzden tüm zaman taşınabilir olmayan kod göndermediniz. 😊)

Şimdi ne var?

Kendi uzmanlığınızı eklemek cazip gelebilir std::swapve std::vector<bool>::referenceancak standart türler için bunu yapmanıza izin verilmez; aslında, libstdc ++ ve libc ++ 'nin uzantı olarak eklemeyi seçtiği aşırı yüklerle çakışır.

Bu nedenle, taşınabilir ve uyumlu olmak için kodunuzu değiştirmeniz gerekir .

Belki de eski moda:

const bool temp = vb[0];
vb[0] = vb[1];
vb[1] = temp;

Veya tam olarak istediğinizi yapan özel statik üye işlevini kullanın :

std::vector<bool>::swap(vb[0], vb[1]);

Ayrıca aşağıdaki gibi dökülebilir:

vb.swap(vb[0], vb[1]);

AFAIK için olması gerekmiyor , ancak buna izin verilir. Uygun kod kırmak sürece onlar kırık kod "Tamam" yapmak için uygulamayı genişletmek olabilir.
NathanOliver

@ NathanOliver-ReinstateMonica Tamam, tamam. En azından bu tür şeylerin kullanımını teşhis etmek zorunda değiller mi? eel.is/c++draft/intro.compliance#8
Yörüngedeki Hafiflik Yarışları

@LightnessRaceswithMonica Bu uzantıyı yasaklayan herhangi bir dil var mı?
Mgetz

@Mgetz Üzgünüm, tüm mevcut dillerde konuşmuyorum, bu yüzden cevaplayamıyorum
Orbit'teki Hafiflik Yarışları

Bu belgeye göre biçimlendirilmemiş uzantıların kullanılıp kullanılmadığından emin değilim . std::vector<bool>::referenceHiçbir şey almaz bir aşırı yük eklediler , aslında hiçbir şey kötü şekillenmemiş. Bana göre bu char * foo = "bar";, kötü biçimlendirilmiş olduğu için teşhis gerektirecek bir şey kullanmak gibi geliyor .
NathanOliver
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.