关于trait和policy的互操作
近日写模板的时候遇到一个问题,与trait和policy之间的互操作有关,下面是简化后的代码:
template < typename T >class TraitSet;template<>class TraitSet< int >{ public: typedef int TypeT;};template<>class TraitSet< long >{ public: typedef long TypeT;};................. //有很多traittemplate< typename T >class DefaultAction{ public : ............ static T GetData( void ) { if( typeid( T ) == typeid( int ) ) { return 10; } if( typeid( T ) == typeid( long ) ) { return 20; } ..................... //有很多个typeid return T( ); } ...............};........................ //有一些policy,每个policy都有GetDatatemplate< typename T, typename Policy = DefaultAction< T >, template < typename > class Trait = TraitSet >class ResultSet{ public : .............. static T GetResult( void ) { .............. typename Trait<T>::TypeT Data = Policy::GetData( ); ............... return Data; } ............};template<>class TraitSet< int >{ public: typedef int TypeT; enum { res = 10 };};template<>class TraitSet< long >{ public: typedef long TypeT; enum { res = 2 };};template< typename T,template < typename > class Trait = TraitSet >class DefaultAction{ public : typedef Traits<T> traits;//把这个代入到ResultSet ............ static T GetData( void ) { return traits::res; } ...............};
[解决办法]
可以对 policy 也特化吧,例如这样。
template <typename T> struct TraitSet;template <> struct TraitSet <int > { typedef int TypeT; };template <> struct TraitSet <long> { typedef long TypeT; };template <typename T> struct DefaultAction { static T GetData () { return T(); } };template <> struct DefaultAction <int > { static int GetData () { return 10; } };template <> struct DefaultAction <long> { static int GetData () { return 20; } };// same thing for OtherAction.
[解决办法]
不清楚楼主的具体需求
用映射应该是比较好的方案吧. 如楼上,,
更通用地可以考虑 Type 到 类类型静态对象的映射.
个人比较看好表驱动.
[解决办法]
>这写法太丑陋了,使用运行时RTTI也有点不爽
杀掉RTTI,在编译器间作选择的方法
std::is_same<T1, T2>::value //(bool value)
如果你的编译器不支援std::is_same
template<typename T1, typename T2>class is_same{ public: enum {value = 0};}template<typename T>class is_same<T, T>{ public: enum {value = 1};};
[解决办法]
lz 忘了可以特化 类成员函数么
template < typename T >class TraitSet;template<>class TraitSet< int >{public: typedef int TypeT;};template<>class TraitSet< long >{public: typedef long TypeT;};template< typename T >class DefaultAction{public : static T GetData( void );};template<>int DefaultAction<int>::GetData(){ return 10;}template<>long DefaultAction<long>::GetData(){ return 20;}int main(){ printf( "%d\n" , DefaultAction<int>::GetData() ); printf( "%d\n" , DefaultAction<long>::GetData() ); return 0;}
[解决办法]
要去掉丑陋的RTTI,需要函数重载或虚函数
#include <iostream>template <typename T>class Traits{public: typedef T value_type;};//重载以去掉RTTIstruct Action1{ static void getData(int& value) { value = 10; } static void getData(char& value) { value = 20; } //....};struct Action2{ static void getData(int& value) { value = 30; } static void getData(char& value) { value = 20; } //....};template<typename T, typename policy, template <typename> class traits>struct ResultSet{ static typename traits<T>::value_type getData() { typename traits<T>::value_type val; policy::getData(val); return val; }};int main(int, char* []){ std::cout << ResultSet<int, Action1, Traits>::getData() << std::endl; std::cout << ResultSet<char, Action2, Traits>::getData() << std::endl; return 0;}
[解决办法]
>lz 忘了可以特化 类成员函数么
这点我上面提过了,其实楼主的问题连is_same都用不到
>要去掉丑陋的RTTI,需要函数重载或虚函数
虽然可以解决问题,但使用virtual会带来执行期间的负担
overload连没有使用的代码都会被具现化
如果追求的是完全的"编译期的运算"(楼主的目标?)
照19楼的写法就好了
简单(虽然建表有点麻烦,可考虑macro)
而且没有呼叫的type就不会被具现化
有可能可以生成较小的二进制码
忘了说,除了C++11,boost也有提供type_traits
此外,虽然很遗憾,但是这类技巧大概不适合拿来和别人共事吧
[解决办法]
template<>int DefaultAction<int>::GetData(){ return 10;}
[解决办法]
template <typename T> struct TraitSet;template <> struct TraitSet <int > { typedef int TypeT; };template <> struct TraitSet <long> { typedef long TypeT; };template <typename T> struct DefaultAction { static T GetData () { return T(); } };template <> struct DefaultAction <int > { static int GetData () { return 10; } };template <> struct DefaultAction <long> { static int GetData () { return 20; } };template< typename T,typename Policy = DefaultAction< T >,template < typename > class Trait = TraitSet >struct ResultSet{ public : static T GetResult( void ) { typename Trait<T>::TypeT Data = Policy::GetData( ); return Data; }};#include <iostream>int main (){ std::cout << ResultSet<int >::GetResult() << std::endl; std::cout << ResultSet<long>::GetResult() << std::endl; return 0;}
[解决办法]
特化什么的在楼主的需求里,代价是大了点.要多写好几个字母,而且费脑子.直接重载就可以了....
template <typename _T>class xxx { inline int _getdata( int * ) { return 1; } inline long _getdata( long * ) { return 2; } inline _T _getdata( ... ) { return _T(); }public: _T GetData() { return _getdata( (_T*)0 ); }};
[解决办法]
无论你怎么简化的代码,根据类型执行不同代码的框架还在啊.
所以,无论是特化,还是重载,还是其它什么方式,都可以满足这个要求吧.
[解决办法]
#include <boost/mpl/vector.hpp>#include <boost/mpl/vector_c.hpp>#include <boost/mpl/map.hpp>#include <boost/mpl/at.hpp>#include <boost/mpl/find.hpp>#include <boost/mpl/begin.hpp>#include <boost/mpl/distance.hpp>#include <boost/static_assert.hpp>#include <boost/type_traits/is_same.hpp>namespace boost{namespace mpl {}}namespace mpl = boost::mpl;struct myclass{ explicit myclass(int){};};typedef mpl::vector<int,long,char,double,myclass,long *> types;template<typename T,typename traint,typename policy>struct ResultSet{ typedef typename mpl::at<traint,T>::type type; typedef typename mpl::distance<typename mpl::begin<types>::type,typename mpl::find<types,type>::type >::type pos; static const int value = mpl::at_c<policy,pos::value>::type::value;};typedef mpl::map5<mpl::pair<int,int>,mpl::pair<long,long>,mpl::pair<char,char>,mpl::pair<double,double>,mpl::pair<myclass,myclass> > traint1; typedef mpl::map5<mpl::pair<int,int*>,mpl::pair<long,long*>,mpl::pair<char,char*>,mpl::pair<double,double*>,mpl::pair<myclass,myclass*> > traint2;typedef mpl::map5<mpl::pair<int,long>,mpl::pair<long,char>,mpl::pair<char,double>,mpl::pair<double,myclass>,mpl::pair<myclass,int> > traint3;typedef mpl::vector_c<int,1,2,3,4,5,6> policy1;typedef mpl::vector_c<int,10,20,30,40,50,60> policy2;typedef ResultSet<long,traint1,policy1> tst1; //identify,long,2BOOST_STATIC_ASSERT(( boost::is_same<tst1::type,long>::value ));BOOST_STATIC_ASSERT(( tst1::value == 2 ));typedef ResultSet<long,traint2,policy1> tst2; //pointer,long *,6BOOST_STATIC_ASSERT(( boost::is_same<tst2::type,long *>::value ));BOOST_STATIC_ASSERT(( tst2::value == 6 ));typedef ResultSet<myclass,traint1,policy2> tst3; //identify,myclass,50BOOST_STATIC_ASSERT(( boost::is_same<tst3::type,myclass>::value ));BOOST_STATIC_ASSERT(( tst3::value == 50 ));typedef ResultSet<myclass,traint3,policy2> tst4; //next,int,10BOOST_STATIC_ASSERT(( boost::is_same<tst4::type,int>::value ));BOOST_STATIC_ASSERT(( tst4::value == 10 ));typedef ResultSet<double,traint3,policy1> tst5; //next,myclass,5BOOST_STATIC_ASSERT(( boost::is_same<tst5::type,myclass>::value ));BOOST_STATIC_ASSERT(( tst5::value == 5 ));int main(){}
[解决办法]
namespace for_actions{ template<typename T> struct def_value { T value; }; template<> struct def_value<int> { enum{value = 10}; }; template<> struct def_value<long> { enum{value = 20}; };}template< typename T >class DefaultAction{public : typedef for_actions::def_value<T> data_reader;};struct A{ A(const std::string& s);};namespace for_actions{ template<> struct def_value<A> { A value; def_value() : value("构造你妹") {} }; }int main(){ DefaultAction<A>::data_reader().value; std::system("pause");}///////////////////// static T GetResult( void ) { .............. typename Trait<T>::TypeT Data = typename Policy::data_reader().value; ............... return Data; }
[解决办法]