2016-04-04 17 views
-1

次のコードは、その後、名前空間の内側に配置されている場合は、その動作していないが、名前空間なしでその...細かい作業型形質は、名前空間の内部で動作していないのはなぜ(STD :: enable_if) - C++ 11

http://ideone.com/goJ0Zf

今まで私が見つけることができるすべては、スカラーデータのための「for_all_ele」は名前空間内で検出されていないのテンプレートの特殊です:

template <typename T,typename _F> 
inline typename std::enable_if< is_iterable<T>::value >::type 
for_all_ele(T&& arr,_F&& fn) 
{ 
    for(auto &x:arr) 
     for_all_ele(x,fn); 

} 

template <typename T,typename _F> 
inline typename std::enable_if< not is_iterable<T>::value >::type 
for_all_ele(T&& x,_F&& fn) 
{ 
    fn(x); 
} 

is_iterableは

完全なコードはここにある...その上に定義されています..

+1

[MCVE]をリンク先に設定していても、ご質問ください。これは、リンク内のコードを取り、問題のない部分を取り除くことを意味します。上のコード*は、名前空間の内側と外側の両方で動作します(何もしません)。 – Yakk

答えて

2

あなたの再帰は、それが見つからないときではなく、Koenig Lookup(別名ADL、Argument Dependent Lookup)によって見つかったときに機能します。

このコール:

{ 
    for(auto &x:arr) 
    for_all_ele(x,fn); 
} 

は見えませんが、後で ない限り xの1または fn ADLを経由して、それを見つけ、 for_all_ele宣言しました。名前空間にないときは、関数と同じ(ルート)名前空間に fnとして渡すラムダが渡されます。だからそれが見つかった。

for_all_eleがネームスペースにある場合、ラムダは異なるネームスペースにあるため、機能しません。

3つのアプローチがあります。

まず、フォワード宣言できます。

第2に、ラッピング機能を作成することができます。次に、おもちゃのタイプ(struct toy_tag{};)をインスタンス化し、その他の引数とともに、for_all_ele_implに渡します。これは、再発時にtoy_tagを通過します。

第三に、あなたは単に終端ケースの後に再帰的なケースを移動することができます。https://ideone.com/17h75Q

template <class T, class F> 
inline typename std::enable_if< is_iterable<T>::value >::type 
for_all_ele(T&& arr,F&& f) 
{ 
    for(auto&&x:arr) 
    for_all_ele(decltype(x)(x),f); 
} 

template <class T, class F> 
inline typename std::enable_if< 
    !is_iterable<T>::value 
>::type 
for_all_ele(T&& t,F&& f) { 
    std::forward<F>(f)(std::forward<T>(t)); 
} 

は私がすべてのコンテキストで標準で予約されている名前_Fとして、あなたの_FからFの名前を変更しました。私はそのように機能オブジェクトを転送するのも完璧です。あなたのコードが完全に転送されていませんでした。

+0

'not' :)' Tとx、Fとfn':P –

+0

@ T.C。 OPから継承されます。しかし、ちょうどもっと従来のものに編集されています。 – Yakk

+0

urアプローチのおかげで、 3番目は私にとってはうまくいきました.2番目のアプローチについてはわかりませんが、前向き宣言アプローチを実装できません。前と同じエラーが表示されます... ここに私の裁判です... [http://ideone.com/x39cMV](http://ideone.com/x39cMV) –

関連する問題