std :: vector範囲コンストラクターは明示的な変換を呼び出すことができますか?


14

次のプログラムは整形式ですか?

#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 [sequence.reqmts]によると、

X u(i, j);

どこXシーケンスコンテナは、されています。

TでなければならEmplaceConstructibleXから*i

ただし、前の段落では、次のように述べられています。

iそして、j表すイテレータは入力イテレータの要件を満たすとに暗黙的に変換要素を指しvalue_type

したがって、両方の要件が満たされる必要があるように思えます:範囲の値の型は、コンテナーの値の型に暗黙的に変換可能 EmplaceConstructibleなければならず、満たす必要があります(つまり、アロケーターは必要な初期化を実行できる必要があります) 。以来intに暗黙的に変換できませんA、このプログラムは、病気に形成されなければなりません。

ただし、驚くべきことに、GCCでコンパイルされているようです。


(記録としては、gccだけではありません:godbolt.org/z/ULeRDw
Max

この場合、明示的なコンストラクターが既に型に適合しているため、暗黙的な変換は必要ありません。説明はわかりにくいと思いますが、明示的な構築は、構築前の暗黙的な変換よりも常に優れています。
-JHBonarius

回答:


2

暗黙的な変換可能性の基準を満たす反復子からの構築をサポートするのは、シーケンスコンテナーの要件のみです。

これだけでは、シーケンスコンテナが、私が知る限り、その基準を満たさないイテレータからの構築をサポートできないようにすることはありません1。それには明確なルールがあります:

コンストラクター...が、入力イテレーターとして適格でない型InputIteratorで呼び出された場合、コンストラクターはオーバーロードの解決に参加しません。

「入力反復子としての資格」がコンテキスト内で正確に何を意味するのかは不明です。Cpp17InputIteratorを表現する非公式な方法ですか、それともiおよびjの要件を参照しようとしますか?知りません。許可されているかどうかにかかわらず、標準にはそれを検出するための厳密な要件はありません。

[container.requirements.general]

特定のコンテナーメンバー関数と演繹ガイドの動作は、型が入力イテレーターまたはアロケーターとして適格かどうかによって異なります。型が入力反復子になり得ないと実装が判断する範囲は、最小整数型が入力反復子としての資格を持たないことを除いて、指定されていません。...

Cpp17InputIteratorは「入力反復子としての資格」があるという解釈により、サンプルプログラムは不正な形式である必要はありません。しかし、それが整形式であることも保証されていません。

1このような場合、依存するときに警告することは、実装品質の問題と見なされる場合があります。一方、暗黙的な変換に対するこの制限は、欠陥と見なされる場合があります。


PSこれは、Clang(libc ++を使用)およびMsvcでも警告なしにコンパイルされます。

PPSこの表現はC ++ 11で追加されたようです(これは、明示的なコンストラクターも導入されたため、当然のことです)。


1
「入力反復子としての資格がない」という意味に本当に依存します上記とは異なり、実際にはとは言えないCpp17InputIteratorため、「暗黙的に変換可能な要素を参照するvalue_typeが「入力反復子」に含まれているかどうかは不明です。そうである場合、コンストラクターはオーバーロードの解決に参加してはならず、プログラムの形式は正しくありません。
マックスラングホフ

1
それで、すべての標準ライブラリクラスは、追加のコンストラクターが使用されたときに診断を発行せずに追加のコンストラクターを持つことができますか?それは直感的に私には間違っているようです...
ブライアン

@ブライアンその「追加のコンストラクター」かどうかはわかりませんが、おそらく「より多くのスペースを可能にするコンストラクターの特定の実装」です。すべての入力をチェックするとパフォーマンスに大きな影響を与える可能性があるため、それが適切な方法かどうかはわかりません...
JHBonarius

@ブライアン明示的に許可されていなくても、確かに悪い考えです。この場合、必要なコンストラクターが、サポートする必要のないタイプのイテレーターをサポートできるかどうかのみを検討しています。この場合、Maxによって指摘されているように、「参加してはならない」という明示的な要件があります。しかし、「入力反復子としての資格」がコンテキスト内で正確に何を意味するかは確かに不明です。非公式な表現方法ですか、それともandのCpp17InputIterator要件を参照しようiとしていjますか?知りません。
eerorika

2
1)C ++では、標準を低く設定します。。2)コンストラクターは非仮想メンバー関数です。3)LWG 3297を参照してください。ただし、暗黙の変換要件を削除する必要があるとは特に確信していません。
TC、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.