2011-01-20 10 views
3

多次元配列(任意のランク)の与えられたサンプリング座標で線形補間を実行する一般的なフィルタリング関数を記述しようとしています。このためには、値とそれに関連する型にヒットするまで、配列のすべての次元を調べる再帰関数テンプレートが必要です。私はboost :: enable_ifを使用して、ディメンションの反復処理をいつ停止するかを検出します。戻り値/型を一番上の関数に "浸透"しようとするまでは正常に動作します。この目的のために、私はC++ 0x型の推論を使用しようとしましたが、boost :: enable_ifとうまく混合していないようです。boost :: enable_ifを使ったC++ 0x型推論の混乱

template< typename T, std::size_t I > 
auto test(const T &t) -> typename boost::enable_if_c< (I == 0), typename T::value_type >::type 
{ 
    return t[0]; 
} 

template< typename T, std::size_t I > 
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type 
{ 
    return test< typename T::value_type, std::size_t(I - 1) >(t[0]); 
} 

コンパイラ(GCC 4.6)を次のコードで文句を言う:

typedef std::array< std::array< float, 1 >, 1 > myarray; 
myarray ma; 
std::cout << typeid (test< myarray, 1 >(ma)).name() << std::endl; 

エラーメッセージ:

error: conversion from 'boost::enable_if_c<true, float>::type' to non-scalar type 'boost::enable_if_c<true, std::array<float, 1u> >::type' requested 

それを

は私が次のものに問題がダウン隔離しましたdecltypeは、指示されているにもかかわらず、テスト< Tからの戻り値を使用しているようです試験番号< T、I - 1>のものを使用する。なぜこの現象が起こるのか?今のところ、私は全体をファンクタに変えると思います...

答えて

4

問題は、decltypeにT()(とT)を渡したことです。タイプは折りたたまれていません。あなたがreturn型をdecltypeに渡したものと比較すると、これは明らかに明らかです - それらは矛盾しています。

template< typename T, std::size_t I > 
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type 
{ 
    return test< typename T::value_type, std::size_t(I - 1) >(t[0]); 
} 

decltype: test<T

return expression: test< typename T::value_type

フォワードこのような関数を定義する場合、戻り値の型を定義するために使用decltype発現は、ほぼ常に、実際のリターン式と全く同じであるべきです。

編集:実際には、異なる結果に終わる可能性があるため、実際には左辺値、特にテンプレートには右値を渡してはいけないと付け加える必要があります。

+0

私はそれを逃していた、ありがとう! – pmjobin