Conditional Typedefs

If I have a little peice o 'code as such ...

template <typename _T> class Foo { public: typedef const T& ParamType; void DoStuff(ParamType thingy); }; 

This may not be optimal if sizeof(_T) <= sizeof(_T*) .

Therefore, I want to have a conditional typedef . If the size of _T less than or equal to the value of the pointer, just pass it by value. Otherwise, pass it via the const link. Is it possible? I heard that all these things are about completing templates, but it hurts me.

+6
c ++ templates
source share
5 answers

It is fairly easy to achieve with a partial specialized specialization .

 template< typename _T, bool _ByVal > struct FooBase { typedef const _T& ParamType; }; template< typename _T > struct FooBase< _T, true > { typedef const _T ParamType; }; template< typename _T, bool _ByVal = sizeof(_T) <= sizeof(void*) > class Foo : public FooBase< _T, _ByVal > { typedef typename FooBase< _T, _ByVal >::ParamType ParamType; void DoStuff(ParamType thingy); }; 

EDIT . According to Jeff sol'n, you really need to compare sizeof(_T) and sizeof(_T&) , but I kept the original requirement <= void* .

+5
source share

You can do it, but it's a little complicated.

My main concern is here if your motive. I understand that you do not want to pass large objects by value, but regardless of whether the large or large object is inconsequential - what you really want to know is how long it will take the copy constructor to create the parameter .

As a concrete example, the size of std::vector is actually very tiny, since it allocates all the memory on the heap and only a pointer is needed. However, copying a vector takes much longer. Something like this is not something you can really include in a state.

Your best bet here is just to pass by const & so that you cover the worst case. In addition, I cannot guarantee this, but I believe that the compiler would be smart enough to go by value if it thought it was more efficient.

+4
source share

You can use Enhance Call Features .

 template <typename _T> class Foo { public: void DoStuff(boost::call_traits<_T>::param_type thingy); }; 

From the documentation:

If T is a small built-in type or pointer, then param_type is defined as T const instead of T const &.

+4
source share
 template <class T, bool Smaller> class BestArgumentPassingType {}; template <class T> class BestArgumentPassingType<T, true> { public: typedef T Type; }; template <class T> class BestArgumentPassingType<T, false> { public: typedef const T& Type; }; template <class T> class ArgumentType : public BestArgumentPassingType<T, sizeof(T) < sizeof(T*)> { }; struct B { double d; double d2; }; struct S { double d; }; class A { public: static void foo(ArgumentType<B>::Type big); static void bar(ArgumentType<S>::Type small); }; int main() { B b; S s; A::foo(b); A::bar(s); return 0; } 

Same.

+4
source share

I know that this is not what you asked for, but it is your goal. I would use another way to achieve this: pass classes (including structures and unions) by reference and pass everything else by value.

 template<typename> struct tovoid { typedef void type; }; template<typename T, typename = void> struct parm_type { typedef T type; }; template<typename T> struct parm_type<T, typename tovoid<int T::*>::type> { typedef T const& type; }; template <typename T> class Foo { public: typedef typename parm_type<T>::type ParamType; void DoStuff(ParamType thingy); }; 

This implements (in my opinion) a very good point that @Poita_ did.

+3
source share

All Articles