Std :: vector range constructor açık dönüşümleri çağırabilir mi?


14

Aşağıdaki program iyi biçimlendirilmiş mi?

#include <vector>
struct A {
    explicit A(int) {}
};
int main() {
    std::vector<int> vi = {1, 2, 3, 4, 5};
    std::vector<A> va(vi.begin(), vi.end());
}

C ++ 17 [sıra.reqmts] 'ye göre,

X u(i, j);

Xbir dizi kabı nerede :

Tolacaktır EmplaceConstructibleiçine Xgelen *i.

Ancak, önceki paragrafta şöyle belirtilmektedir:

ive jgirdi yineleyici gereksinimlerini karşılayan yineleyicileri belirtir ve dolaylı olarak dönüştürülebilir öğelere başvurur value_type,

Böylece hem gereksinimlerin karşılanması gerekir geliyor bana: aralığının değer türü kabın değeri türüne örtük olarak dönüştürülebilir olmalıdır, ve EmplaceConstructible (allocator gerekli başlatma gerçekleştirmek gerekir anlamına gelir) yerine getirilmesi gerekir . Yana intörtük olarak dönüştürülebilir değildir A, bu program kötü şekillendirilmiş olmalıdır.

Ancak, şaşırtıcı bir şekilde, GCC altında derleniyor gibi görünüyor .


(Kayıt için, sadece gcc değil: godbolt.org/z/ULeRDw )
Max Langhof

Bu durumda, açık kurucu türe zaten uyduğundan örtük dönüştürme gerekmez. Açıklamanın kafa karıştırıcı olduğunu düşünüyorum, ancak açık inşaat her zaman inşaattan önce örtük dönüşümden daha iyidir.
JHBonarius

Yanıtlar:


2

Sıralı kapların, örtük konvertibilite kriterlerini karşılayan iteratörlerden yapıyı desteklemesi sadece bir gerekliliktir.

Bu, kendi başına dizi kapsayıcılarını, bu yapıyı, 1'e kadar söyleyebildiğim kadarıyla bu kriterleri karşılamayan yineleyicilerden desteklemekten alıkoymaz . Bununla ilgili açık bir kural var:

Yapıcı ... girdi yineleyicisi olarak nitelendirilmeyen bir InputIterator türü ile çağrılırsa , kurucu aşırı yük çözümüne katılmayacaktır.

"Girdi yineleyici olarak nitelendirme" ifadesinin tam olarak bağlamda ne anlama geldiği belirsizdir. Cpp17InputIterator ifade etmek için gayri resmi bir yol mudur, yoksa i ve j gereksinimlerine başvurmaya çalışıyor mu? Bilmiyorum. İzin verilse de edilmesin, standardın tespit edilmesi için katı bir gereksinimi yoktur:

[Container.requirements.general]

Belirli kap üyesi işlevlerinin ve tümdengelim kılavuzlarının davranışı, türlerin girdi yineleyici veya ayırıcı olarak nitelendirilmesine bağlıdır. Bir uygulamanın bir türün bir girdi yineleyicisi olamayacağını belirleme derecesi, minimum integral tiplerinin girdi yineleyici olarak nitelendirilmemesi dışında, belirtilmez. ...

Herhangi bir Cpp17InputIterator "girdi yineleyici" olarak nitelendirilir yorumlama ile, örnek programın kötü biçimlendirilmesi gerekmez. Ancak iyi biçimlendirilmiş olması da garanti edilmez.

1 Böyle bir durumda, ona güvenirken uyarılması bir uygulama kalitesi sorunu olarak düşünülebilir. Öte yandan, örtük dönüşümlere yönelik bu sınırlama bir kusur olarak değerlendirilebilir .


PS Bu, Clang (libc ++ ile) ve Msvc'de de uyarı yapılmadan derlenir.

PPS Bu ifadeler C ++ 11'e eklenmiş gibi görünmektedir (bu doğaldır, o zaman açık kurucular da getirilmiştir).


1
Gerçekten "bir girdi yineleyici olarak nitelendirilmez" ne demek bağlıdır . Aksine yukarıda , aslında demiyor Cpp17InputIteratoro olsun bana açık değil bu yüzden, "ve örtük olarak dönüştürülebilir öğelerini ifade value_type" "giriş yineleyici" dahildir. Eğer öyleyse, kurucu aşırı yük çözünürlüğüne katılmamalı ve program kötü biçimlendirilmelidir.
Max Langhof

1
Yani, her standart kütüphane sınıfının bu ekstra kurucular kullanıldığında tanı koymadan ekstra kuruculara sahip olmasına izin verilir? Bu sezgisel olarak bana yanlış geliyor ...
Brian

@Brian emin değilim onun "ekstra yapıcılar", ama belki daha "belirli uygulamaları daha fazla alan için izin" ". Her girdinin kontrol edilmesi önemli performans etkisine sahip olabilir, bu yüzden bu yolun gidip gitmeyeceğini bilmiyorum ...
JHBonarius

@Brian Açıkça izin verilmese bile kesinlikle kötü bir fikir olurdu. Bu durumda, yalnızca gerekli bir kurucunun desteklemesinin gerekmediği yineleyici türlerini desteklemesine izin verilip verilmediğini düşünüyoruz. Bu durumda, Max'in işaret ettiği gibi, buna kesinlikle izin vermeyecek açık bir "katılmayacak" koşulu vardır. Ancak "girdi yineleyici olarak nitelendirme" ifadesinin tam olarak bağlamda ne anlama geldiği açık değildir. O ifade etmek gayri yolu mu Cpp17InputIterator, yoksa gereklerine atıfta girişiminde mu ive j? Bilmiyorum.
eerorika

2
1) C ++ 'da standardı düşük ayarladık. . 2) Yapıcılar sanal olmayan üye işlevlerdir . 3) Bakınız LWG 3297 ; ancak örtük dönüşüm gereksinimini kaldırmamız gerektiğine ikna olmadım.
TC
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.