2011-01-02 18 views
4

私は、値と一連のルックアップテーブルを引数として取る変換関数を記述しようとしています。私はそれが次のテンプレート関数の宣言を変換で動作するように取得することができますC++テンプレート関数の質問

template< typename fromType, typename toType> struct DataTranslator; 

:ルックアップテーブルは次の宣言がある

DataTranslator<specificBaud, universalBaud>::type baudTranslator; 
DataTranslator<universalBaud, std::string>::type baudCmdTranslator; 

specificBaud myBaud; 
.... 
std::string result = translate<std::string, forward_trans>(myBaud, baudTranslator, baudCmdTranslator); 

template< typename Return, typename Direction, typename ValType, typename TransType> 
Return translate(ValType val, TransType& trans); 

template< typename Return, typename Direction, typename ValType, typename TransType, typename... OtherTrans> 
Return translate(ValType val, TransType& trans, OtherTrans&... others); 

を私は次のような何かを行うことができます

翻訳機能の宣言を次のように変更した場合:

template< typename Return, typename Direction, typename ValType, typename FT, typename TT> 
Return translate(ValType val, typename DataTranslator<FT, TT>::type& trans); 

template< typename Return, typename Direction, typename ValType, typename FT, typename TT, typename... OtherTrans> 
Return translate(ValType val, typename DataTranslator<FT, TT>::type& trans, OtherTrans&... others); 

変換呼び出しを行うときに、関数呼び出しに一致しないエラーが発生しました。私は-std = C++ 0xフラグをつけて私のコンパイラにGCC 4.5を使っています。

私の主な質問は、なぜ2番目のバージョンが機能しないのですか?私は、それを専門化するタイプの分解のタイプを行う例(主にバリッドテンプレートの提案の1つに入れられたTupleクラス)を見てきました。

完全なテストコード:

/* 
* bimap_test.cpp 
* 
* Created on: Dec 27, 2010 
*  Author: natejohn 
*/ 

#include <iostream> 
#include <utility> 
#include <string> 
#include <boost/multi_index_container.hpp> 
#include <boost/multi_index/ordered_index.hpp> 
#include <boost/multi_index/member.hpp> 
#include <boost/multi_index/tag.hpp> 
#include <boost/mpl/if.hpp> 
#include <boost/function.hpp> 
#include <tr1/type_traits> 

enum silly {car, boat, plane, truck}; 
enum furry {bunny, dog, cat, donkey, critter}; 

struct forward_trans {}; 
struct reverse_trans {}; 

template<typename from, typename to> struct DataTranslator 
{ 
    typedef std::pair<from, to> Element; 
    typedef boost::multi_index_container<Element, boost::multi_index::indexed_by< 
      boost::multi_index::ordered_unique< 
      boost::multi_index::tag<forward_trans>, 
      boost::multi_index::member<Element, typename Element::first_type,  &Element::first> 
      >, 
      boost::multi_index::ordered_unique< 
     boost::multi_index::tag<reverse_trans>, 
     boost::multi_index::member<Element, typename Element::second_type, &Element::second> 
     > 
     > 
> type; 

    // Added after Answer accepted as what I fixed to get this to work 
    type trans; 


}; 

template<typename R, typename I> struct forward_extractor 
{ 
    R operator()(I it) { return it->second; } 
}; 

template<typename R, typename I> struct reverse_extractor 
{ 
    R operator()(I it) { return it->first; } 
}; 

template<typename from, typename to> struct FunctionTranslator 
{ 
    typedef boost::function<to (from) > forward_type; 
    typedef boost::function<from (to) > reverse_type; 
}; 

/*template<typename R, typename D, typename V, typename Trans> 
R translate(V v, Trans& t); 

template<typename R, typename D, typename V, typename Trans, typename... Others> 
R translate(V v, Trans& t, Others&... o); 
*/ 

template<typename R, typename D, typename V, typename FT, typename TT, typename...  others> 
R translate(V val, boost::function<TT(FT)> trans, others&... o) 
{ 
    TT temp = trans(val); 
    return static_cast<R>(translate<R, D>(temp, o...)); 
} 

template<typename R, typename D, typename V, typename FT, typename TT> 
R translate(V val, boost::function<TT(FT)>& func) 
{ 
    return static_cast<R>(func(val)); 
} 

template<typename R, typename D, typename V, typename FT, typename TT> 
R translate(V val, typename DataTranslator<FT, TT>::type& trans) 
{ 
    typedef typename DataTranslator<FT, TT>::type::template index<D>::type lookup_table; 
    typedef typename lookup_table::iterator lut_iterator; 
    lookup_table& lut = boost::multi_index::get<D>(trans); 

R not_found; 

typedef typename boost::mpl::if_c<std::tr1::is_same<D, forward_trans>::value, forward_extractor<TT, lut_iterator>, 
      typename boost::mpl::if_c<std::tr1::is_same<D, reverse_trans>::value, reverse_extractor<FT, lut_iterator>, bool>::type>::type extractor_type; 

extractor_type ext; 

lut_iterator it = lut.find(val); 

if(it == lut.end()) 
{ 
    return not_found; 
} 

return static_cast<R>(ext(it)); 

} 


template<typename R, typename D, typename V, typename FT, typename TT, typename... others> 
R translate(V val, typename DataTranslator<FT, TT>::type& trans, others&... o) 
{ 
typedef typename DataTranslator<FT, TT>::type::template index<D>::type lookup_table; 
typedef typename lookup_table::iterator lut_iterator; 
lookup_table& lut = boost::multi_index::get<D>(trans); 
R not_found; 
typedef typename boost::mpl::if_c<std::tr1::is_same<D, forward_trans>::value, forward_extractor<TT, lut_iterator>, 
      typename boost::mpl::if_c<std::tr1::is_same<D, reverse_trans>::value, reverse_extractor<FT, lut_iterator>, bool>::type >::type extractor_type; 
extractor_type ext; 


lut_iterator it = lut.find(val); 

if(it == lut.end()) 
{ 
    return not_found; 
} 

return translate<R, D>(ext(it), o...); 

} 


int main(int argc, char** argv) 
{ 
typedef typename DataTranslator<silly, furry>::type SillyToFurryTranslatorType; 
typedef typename DataTranslator<furry, std::string>::type FurryToStringTranslatorType; 


DataTranslator<silly, furry>::type stft; 
DataTranslator<furry, std::string>::type ftst; 

stft.insert(std::make_pair(car, dog)); 
stft.insert(std::make_pair(boat, cat)); 
ftst.insert(std::make_pair(dog, "Doggie!")); 
ftst.insert(std::make_pair(cat, "Earl the Dead Cat")); 

std::string result = translate<furry, forward_trans>(car, stft, ftst); 
std::cout << result << std::endl; 

return 0; 
} 

+1

第2引数型の::型がなぜですか? 'translate(ValType val、DataTranslator &trans)'を使ってみましたか? –

+0

'translate (myBaud、baudTranslator、baudCmdTranslator)'の2番目の関数を呼び出していましたか? – chrisaycock

+0

@Giuseppe Ottaviano:the :: typeは、DataTranslator構造体が単に型を保存するために使用されるためです。これはtypedefのペアであり、std :: pairの最初のもので、2番目のものはboost :: multi_index_containerです。 :: typeはmulti_index_containerです。私は私が持っているプロジェクトで100以上のこれらのルックアップテーブルで終わるので、DataTranslator構造体によって提供されるtypedefは、1000行の反復コードを保存するように見えます。 – diverscuba23

答えて

4

私はこの問題は、あなたが内側にネストされたいくつかの種類のタイプからアウタークラスの型を推測しようとした場合、C++テンプレート引数控除が故障していることだと思いますそれであれば。たとえば、これは正しく動作しません。

template <typename T> void DoSomething(typename std::vector<T>::iterator itr); 

std::vector<int> v; 
DoSomething(v.begin()); 

この理由は、コンパイラが明確アウタータイプは、すべての場合でなければなりませんかを決定することができないということです。

template <typename T> class Pathological { 
     typedef int type; 
}; 

template <typename T> void WhatIsT(typename Pathological<T>::type huh); 

ここでの問題は、病理学のすべてのインスタンス化はその型のタイプに指定したのと同じタイプを持っていることである。例えば、このような場合を考えます。したがって、Pathological<int>::typeまたはPathological<double>::typeを渡す場合、両方の型がintに評価されるため、コンパイラは外部型が何であるかを判断できませんでした。

希望すると便利です。

+0

ありがとうございます。それが私の問題でした。 – diverscuba23