次のコードは、T
がbegin
とend
メソッドを持っているかどうかを検出する必要がありますトラブル1 1 1 1
です。ただし、Visual Studio 2008では、出力は1 1 0 0
です。私は何か間違ったことをしたのですか、これは単にVS 2008のバグですか?誰か別のコンパイラでテストできますか?ありがとう!SFINAEコンパイラは、鉱山の
答えて
ステファンT. Lavavejが言ってthisがあります
標準ライブラリのメンバ関数のアドレスを取得することが技術的に禁止されていることに注意してください。(彼らは
&foo::bar
があいまいなって、過負荷状態にすることができ、それらはstatic_cast
を経由して明確にする試みを破って、追加のデフォルト引数を持つことができます。)
だから私は、私だけをチェックする簡単なバージョンを使用するつもりだと思います入れ子になったconst_iterator
タイプ。
ここでは、これらのことをデバッグする方法について説明します。
まず、否定的な選択肢をコメントアウトして、不一致ではなくエラーになるようにします。 次に、動作しない項目の1つを使用して、関数に入れている型をインスタンス化してみてください。
この手順では、あなたのsfinaeオブジェクトをインスタンス化できましたが、まだ動作していませんでした。これは、それがVSバグであることを私に知らせるので、問題はそれを修正する方法です。
あなたがしているようにVSがSFINAEに問題があるようです。あなたがあなたのsfinaeオブジェクトを包むとき、それはより良く機能します。
template <typename U, typename it_t = typename U::const_iterator >
struct sfinae
{
// typedef typename U::const_iterator it_t; - fails to compile with non-cont types. Not sfinae
template < typename U, typename IT, IT (U::*)() const, IT (U::*)() const >
struct type_ {};
typedef type_<U,it_t,&U::begin,&U::end> type;
};
まだ働いていなかったが、少なくとも私は有益なエラーメッセージました:私はそうなどがあることでした
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'std::_Tree_const_iterator<_Mytree> (__thiscall std::set<_Kty>::*)(void) const'
をこれは私が&U::end
はVSがするには十分ではないことを知ることができますどのエンド()が欲しいかを知ることができます。 static_castは次のように修正しました:
typedef type_<U,it_t,static_cast<it_t (U::*)() const>(&U::begin),static_cast<it_t (U::*)() const>(&U::end)> type;
VS2010で成功したテストプログラムを実行してください。 static_castは実際に必要なものすべてであるかもしれませんが、私はそれをあなたに残しておきました。
今実際の質問は、どのコンパイラが正しいのでしょうか?私の賭けは一貫していたものです:g ++。
編集:ジェエッシュ...
template <typename T>
struct is_container
{
template <typename U, typename it_t = typename U::const_iterator >
struct sfinae
{
//typedef typename U::const_iterator it_t;
template < typename U, typename IT, IT (U::*)() const, IT (U::*)() const >
struct type_ {};
typedef type_<U,it_t,static_cast<it_t (U::*)() const>(&U::begin),static_cast<it_t (U::*)() const>(&U::end)> type;
};
template <typename U> static char test(typename sfinae<U>::type*);
template <typename U> static long test(...);
enum { value = (1 == sizeof test<T>(0)) };
};
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <map>
int main()
{
std::cout << is_container<std::vector<std::string> >::value << ' ';
std::cout << is_container<std::list<std::string> >::value << ' ';
std::cout << is_container<std::set<std::string> >::value << ' ';
std::cout << is_container<std::map<std::string, std::string> >::value << ' ';
std::cout << is_container<bool>::value << '\n';
}
@sbi @John @Rup悲しいことに、このコードは動作しません。型が 'begin'または' end'メソッドを持たない場合、型はコンパイルされません。 – fredoverflow
@Fred:しかし、元のコードでも 'begin()'/'end()'をチェックしましたか? (どのクラスも入れ子の 'const_iterator'型を持ちますが、' begin() '/' end() 'は返さないのですか?) – sbi
@sbi:SFINAEは"置換の失敗は** **エラーではありません "を意味します。 'T'が' begin'と 'end'メソッドを持たない場合、' is_container
なぜあなたはすべての努力をしていますか? U::begin()
が存在するかどうか確認したい場合は、試してみてください。U::begin()
とU::end()
の存在をチェックをすることに加え
template <typename T>
struct is_container
{
template <typename U> static char test(U* u,
typename U::const_iterator b = ((U*)0)->begin(),
typename U::const_iterator e = ((U*)0)->end());
template <typename U> static long test(...);
enum { value = (1 == sizeof test<T>(0)) };
};
、これはまた、彼らはconst_iterator
に変換可能である何かを返すかどうかをチェックします。 Stephan T. Lavavejによって強調された落とし穴を、特定の署名を前提とするのではなく、サポートしなければならない呼び出し式を使って回避します。
[編集] 申し訳ありませんが、これはVC10のテンプレートのインスタンスに依存していました。より良いアプローチは、(オーバーロードに参加してください引数の型でexistanceチェック、置き):
template <typename T> struct is_container
{
// Is.
template <typename U>
static char test(U* u,
int (*b)[sizeof(typename U::const_iterator()==((U*)0)->begin())] = 0,
int (*e)[sizeof(typename U::const_iterator()==((U*)0)->end())] = 0);
// Is not.
template <typename U> static long test(...);
enum { value = (1 == sizeof test<T>(0)) };
};
VS2005でテストしましたが、 'is_container
'typename U :: const_iterator b =((U *)0) - > begin()' 'begin()'() ')が呼び出されないという概念を説明してもらえますか? 、ありがとうたくさん:) –
@ Mr.Anubis:デフォルトの引数は、関数が呼び出された時点で評価されます。 'test
これはおそらくする必要がありますコメントを、私は十分なポイント
@MSalters
を持っていませんあなたのis_container
作品は(ほとんど)と私はあなたのコードを自分自身を使用していたにもかかわらず
が、私はそれに2つの問題を発見しました。
まずタイプdeque<T>::iterator
が(GCC-4.7で)コンテナとして検出されることです。 deque<T>::iterator
がbegin
/end
メンバーと定義されてconst_iterator
タイプを持っているようです。
第2の問題は、このコードは、GCCの開発者によれば無効であることです。私qoute:デフォルトの引数の値は、関数型の一部ではなく、控除には含まれません。私は現在、is_container<T>
のために(C++ 11のみ)thisを使用していますGCC bug 51989
を参照してください:C++ 11で
template <typename T>
struct is_container {
template <
typename U,
typename S = decltype (((U*)0)->size()),
typename I = typename U::const_iterator
>
static char test(U* u);
template <typename U> static long test(...);
enum { value = sizeof test<T>(0) == 1 };
};
'deque'はコンテナではありませんか? – fredoverflow
'deque'はコンテナですが、' deque
第2の問題は本当です。私は14.7.1/2を見落とした。デフォルトの引数は、テンプレート自身でインスタンス化されません。 – MSalters
、これを検出するためのより良い方法が存在することになります。代わりに、関数のシグネチャに頼るので、私たちは単に表現SFINAEコンテキストでそれらを呼び出す:
#include <type_traits> // declval
template<class T>
class is_container{
typedef char (&two)[2];
template<class U> // non-const
static auto test(typename U::iterator*, int)
-> decltype(std::declval<U>().begin(), char());
template<class U> // const
static auto test(typename U::const_iterator*, long)
-> decltype(std::declval<U const>().begin(), char());
template<class>
static two test(...);
public:
static bool const value = sizeof(test<T>(0, 0)) == 1;
};
Live example on Ideone.int
とlong
パラメータは、コンテナの両方を提供しています(またはiterator
がtypedef const_iterator iterator
であれば時にオーバーロードの解決を明確にするだけであり、 std::set
のように) - 0
のタイプはint
であり、最初の過負荷が選択されます。
- 1. 鉱山のウェブクローラで
- 2. 空のベクターは、鉱山の
- 3. 鉱山の地雷数Java
- 4. マージ後のインタラクティブリベース/その他インターリーブ鉱山
- 5. 鉱山以外のフィードにCSSを追加するには
- 6. 2008 SQL EXPRESSストアドプロシージャ - 鉱山が見つかりません
- 7. 鉱山.csvファイルがアップロードされていませんか?
- 8. django-admin makemessages =>すべてのdjangoパッケージを鉱山で翻訳する
- 9. キューのメモリを解放するには?鉱山は無料ではありません
- 10. 地雷鉱山のゲームは、スイッチのステートメントのみを使用しています...エラーが発生しました,,,,?
- 11. 鉱山フレーズ(3ワードまで)私は私の問題に簡単な解決策のために前に頼ま
- 12. 特定のアプリケーション(鉱山ではない)がユーザーに表示/非表示になったときの検出
- 13. Firefoxで鉱山のページをキャッシュするのを止めるにはどうすればいいですか?
- 14. WPF:私は私のプロジェクトにアナログクリックを追加しようとしている鉱山
- 15. PHPは、クラス関数とプロパティが同じ名前を共有できるようにしますか?鉱山の
- 16. Javaの掃除機のゲームの問題。ゲーム開始時に鉱山を隠している?
- 17. 1つのChromeインスタンス(鉱山)のページで不思議にFacebookのログインが失敗する
- 18. SFINAEの理解
- 19. は鋸山
- 20. NSSharingServiceは山のライオンに山のライオンにウィンドウ
- 21. SFINAEとSFINAEでg ++とclang ++の動作が異なる
- 22. SFINAE:コンパイラは、私が<a href="http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error" rel="noreferrer">SFINAE</a>問題持っている専門的なテンプレートクラス
- 23. 鋸山
- 24. 鋸山
- 25. 鋸山
- 26. 鋸山
- 27. フォームPOSTメソッドの戻りHTTPエラー405.0方法は、鉱山からのページには、次のようにformタグを持っている
- 28. Hpricot /鋸山
- 29. 杉山アンドロイド
- 30. 「表現SFINAE」とは何ですか?
( '1 1 1 1 'を得た)のMinGW G ++ 4.4.0に私のために働きました。残念ながら私はVS2008でなぜ失敗するのかわかりませんが、コードは正しいように見えます。 –
VS2010で '1 1 0 0'と同じです。私はSTLをデバッグしているかもしれないが、 '/ DDEBUG'と'/DNDEBUG'を試しましたが、何の違いもありませんでした。 – Rup
Boost.MPLから提供されている['HAS_XXX'ファシリティ](http://live.boost.org/doc/libs/1_34_0/boost/mpl/has_xxx.hpp)を見て、どのように回避できるか見てみましょう特定のコンパイラのSFINAEの容量が制限されています。 –