質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

580閲覧

イテレータのペアを取るstd::vectorのコンストラクタのSFINAEの条件

yumetodo

総合スコア5850

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2018/01/31 09:12

std::vectorには

cpp

1template <class InputIter> 2vector(InputIter first, InputIter last, 3 const Allocator& a = Allocator());

のようなコンストラクタがC++03より存在します。

vector::コンストラクタ - cpprefjp C++日本語リファレンス
によると、
C++03までは整数のペアを渡せたようですが、

C++11 では InputIter が入力イテレータの要件を満たさなければオーバーロード解決に参加しないように変更された。

と書かれています。しかし規格書(N4140)を参照すると、

template <class InputIterator> vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); 9 Effects: Constructs a vector equal to the range [first,last), using the specified allocator. 10 Complexity: Makes only N calls to the copy constructor of T (where N is the distance between first and last) and no reallocations if iterators first and last are of forward, bidirectional, or random access categories. It makes order N calls to the copy constructor of T and order log(N) reallocations if they are just input iterators.

のようにあり、それらしい文言はありません。

実際libstdc++の実装を見ると、

cpp

1 template<typename _InputIterator, 2 typename = std::_RequireInputIter<_InputIterator>> 3 vector(_InputIterator __first, _InputIterator __last, 4 const allocator_type& __a = allocator_type()) 5 : _Base(__a) 6 { _M_initialize_dispatch(__first, __last, __false_type()); } 7

のようにSFINAEで弾くように書かれています。

ところでVisial Studio 2017の実装を見ると、

cpp

1 template<class _Iter, 2 class = enable_if_t<_Is_iterator_v<_Iter>>> 3 vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) 4 : _Mybase(_Al) 5 { // construct from [_First, _Last) with optional allocator 6 _DEBUG_RANGE(_First, _Last); 7 _Range_construct_or_tidy(_Unchecked(_First), _Unchecked(_Last), _Iter_cat_t<_Iter>{}); 8 }

のようになっており、これは入力イテレータであるかの検査と言うよりはイテレータであるかの検査に見えます。


質問です。

  1. 入力イテレータではないときオーバーロード解決から外すというこの文言の根拠となる規格書の文面はどこか
  2. MSVCの実装は規格に準拠しているか

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

1.入力イテレータではないときオーバーロード解決から外すというこの文言の根拠となる規格書の文面はどこか

23.2.3 [sequence.reqmts]/paragraph14にあります:

For every sequence container defined in this Clause and in Clause 21:

  • If the constructor
template <class InputIterator> X(InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type())

is called with a type InputIterator that does not qualify as an input iterator, then the constructor shall not participate in overload resolution.

C++標準ライブラリコンテナでは、個別クラスの外部仕様と一般コンテナ要件の両者をあわせて参照ください。


  1. MSVCの実装は規格に準拠しているか

_Is_iterator_vメタ関数の実装次第ですが、名前からは単にイテレータであるか否かをチェックしているようにも読めますね。この場合、出力イテレータ(output iterator)を指定したときにオーバーロード解決に影響してしまうため、厳格には仕様違反となりそうです。(とはいえ、実用上問題になるケースは考えづらいですけど...)

投稿2018/01/31 11:06

yohhoy

総合スコア6189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2018/01/31 15:16

>C++標準ライブラリコンテナでは、個別クラスの外部仕様と一般コンテナ要件の両者をあわせて参照ください。 vectorの付近しか読んでいないのがバレてしまったでござる >_Is_iterator_vメタ関数の実装次第ですが 単にイテレータであるかしか見てないですね。仕様違反か。(もちろん実害はないでしょうが)
yohhoy

2018/02/01 02:00

:+1: (過去バグレポで使われていたMicrosoft Connectって終了してたんですね…)
yumetodo

2018/02/02 03:14

なんか、C++17からは§ 26.2.1 [container.requirements.general]/17 "The extent to which an implementation determines that a type cannot be an input iterator is unspecified, except that as a minimum integral types shall not qualify as input iterators."があるからこれでええんやで、とか言っていて、いや待てよお前ら_MSVC_LANGが201402Lのときどうするんだよ、という思い
yumetodo

2018/11/28 18:58

そういえばこの件、曰くC++98まで遡及適用されるよって話だってことをここには書いていなかった。この質問にたどり着くマニアックな人のために
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問