C++模板函数题 [英] C++ template function question

查看:45
本文介绍了C++模板函数题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个将值和一系列查找表作为参数的转换函数.查找表具有以下声明:

I am trying to write a translation function that takes the value and the 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 translate template function declarations:

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

然后我可以执行以下操作:

I can then 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 change the declaration of my translate 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);

在进行翻译调用时,我收到了没有匹配的函数调用错误.我使用 GCC 4.5 作为带有 -std=c++0x 标志的编译器.

I get a no matching function call error when making the translate call. I'm using GCC 4.5 for my compiler with the -std=c++0x flag.

我的主要问题是为什么第二个版本不起作用?我见过一些例子(主要是在一个可变模板提案中提出的一个 Tuple 类),他们对一个类型进行那种类型的分解来专门化它.

My main question is why does the second version not work? I have seen examples (mainly a Tuple class put forward in one of the proposals for varidic templates) where they do that type of decomposition of a type to specialize it.

完整的测试代码:

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

推荐答案

我认为问题在于,如果您尝试从嵌套在内部的某种类型的类型推导出外部类的类型,则 C++ 模板参数推导会失败,如果它.例如,这将无法正常工作:

I think the problem is that C++ template argument deduction breaks down if you try to deduce the type of an outer class from the type of some type nested inside if it. For example, this won't 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 can't unambiguously determine what the outer type must 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);

这里的问题是 Pathological 的每个实例都为其类型类型指定了相同的类型.因此,如果您要传入 Pathological::typePathological::type,编译器无法确定外部类型是什么是因为这两种类型的计算结果都是 int.

The problem here is that every instantiation of Pathological has the same type specified for its type type. Consequently, if you were to pass in a Pathological<int>::type or a Pathological<double>::type, the compiler couldn't determine what the outer type was because both of those types evaluate to int.

希望这会有所帮助!

这篇关于C++模板函数题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆