C ++ template function task

I am trying to write a translation function that takes a value and a series of lookup tables as arguments. The lookup table has the following declaration:

template< typename fromType, typename toType> struct DataTranslator; 

I can get it to work with the following declarations of the transformable template function:

 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); 

Then I can do something like the following:

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

but if I changed the declaration of my translation functions to:

 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); 

When making a transferred call, I get an inappropriate function call error. I am using GCC 4.5 for my compiler with the flag -std = C ++ 0x.

My main question is: why does the second version not work? I saw examples (basically, the Tuple class proposed in one of the sentences for varidic templates), where they make this type of type decomposition for its specialization.

Full test code:

 /* * 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; } 

+4
source share
1 answer

I think the problem is that the output of the C ++ template's template argument breaks if you try to infer the type of the outer class from the type of some type nested inside if it is. For example, this will not work correctly:

 template <typename T> void DoSomething(typename std::vector<T>::iterator itr); std::vector<int> v; DoSomething(v.begin()); 

The reason for this is that the compiler cannot unambiguously determine what external type should be in all cases. For example, consider this case:

 template <typename T> class Pathological { typedef int type; }; template <typename T> void WhatIsT(typename Pathological<T>::type huh); 

The problem here is that every Pathological instance has the same type specified for its type type. Therefore, if you had to pass the Pathological<int>::type or Pathological<double>::type , the compiler could not determine what the external type is because both of these types evaluate to int.

Hope this helps!

+4
source

Source: https://habr.com/ru/post/1334000/


All Articles