10

std::beginカスタムコンテナに特化しようとしています。forコンテナで範囲ベースを使用したいので、これを行っています。これは私が持っているものです:

class stackiterator { … };
class stack { … };

#include <iterator>

template <> stackiterator std::begin(stack& S)
{
  return S.GetBottom();
}

begin専門分野の定義で次のエラーが発生します。

関数テンプレートの特殊化 'begin' に一致する関数テンプレートはありません

私は何を間違っていますか?

4

3 に答える 3

14

std::beginカスタムコンテナに特化しようとしています。forコンテナで範囲ベースを使用したいので、これを行っています。

あなたは間違った木を吠えています。範囲ベースforは一切使用std::beginしません。クラス型の場合、コンパイラはメンバーbeginを直接検索し、どちらも見つからない場合は、関連付けられた名前空間でend無料で ADL のみの検索を行いbeginます。end通常の非修飾ルックアップは実行されません。クラスが名前空間std::beginにない場合、 を取得する方法はありません。std

実行したい特殊化が可能であっても (メンバーを導入しない限り不可能ですbegin()。関数テンプレートの明示的な特殊化は戻り値の型を変更できず、問題のオーバーロードは「メンバーbegin()が返すものは何でも」を返します。 member を導入するのにbegin()、なぜstd::beginとにかくそれが行うであろうことを行うことに特化しているのですか?)、それでも range-based でそれを使用することはできませんfor

于 2015-07-16T05:41:35.663 に答える
1

ループbeginを有効にする無料の関数を追加する正しい方法は、 の名前空間に、それぞれ iterator と const_iterator を返す関数 (およびの場合も同様)を追加することです。for(:)stackbegin(stack&)begin(stack const&)end

begin()もう 1 つの方法は、メンバーを追加しend()stack.

特殊化std::beginは多くの理由で悪い習慣であり、そのうちの少なくとも 1 つは、すべてのfor(:)ループがそれで機能するとは限らないことです (ルックアップ ルールは、この欠陥レポートの解決で変更されました)。オーバーロードstd::beginは未定義の動作です (標準の下で関数をオーバーロードすることはできません。オーバーロードnamespace stdすると、プログラムの形式が崩れます)。

プロジェクトの命名規則に違反している場合でも、これが行われなければならない方法です。

于 2015-07-16T14:28:10.110 に答える