Sign in to follow this  
Red Ant

[C++] typedef'ing ugly template functions with long template args?

Recommended Posts

Hello, Assuming I have a template ...
template < class T, class U, class V, class W > class MyClass
{
public:
    static void someFunc();
};

I can do this to cut down on the typing I need to do to access the class ...
typedef MyClass< int, double, int, char > UseThis;

// Make an instance.
UseThis AnInstance;

But can I do something like that for the someFunc() method, too? If so, how?

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
Hello,

Assuming I have a template ...

*** Source Snippet Removed ***


I can do this to cut down on the typing I need to do to access the class ...

*** Source Snippet Removed ***

But can I do something like that for the someFunc() method, too? If so, how?


Something like this?
typedef MyClass< int, double, int, char > UseThis;
UseThis::someFunc();


Or do you want it to be a single identifier? Then you can use #define or a function pointer.

Share this post


Link to post
Share on other sites
Yeah sorry, I just realized that I haven't correctly described my problem.


template < class T, class U, class V, class W > class MyClass
{

};

template < class T, class U, class V, class W >
MyClass< T, U, V, W >* makeInstance()
{
return new MyClass< T, U, V, W >;
}



That's what I really want. Is it possible to make the makeInstance() function more easily accessible via some typedef magic?

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
Yeah sorry, I just realized that I haven't correctly described my problem.

*** Source Snippet Removed ***

That's what I really want. Is it possible to make the makeInstance() function more easily accessible via some typedef magic?


You could do something like this:
template < class T, class U, class V, class W > class MyClass
{
};

template < class T, class U, class V, class W >
MyClass< T, U, V, W >* makeInstance()
{
return new MyClass< T, U, V, W >;
}

MyClass<int,double,int,char>* (*const makeInstance_simple)() = &makeInstance< int, double, int, char>;



It could in theory have some overhead, but I bet any compiler could optimize it away. If you check the assembly (release mode) and find it didn't optimize it, and you really need the optimization, then you could do this:

#define makeInstance_simple makeInstance<int, double, int, char>


EDIT: Of course there is still many ways to do this, the following would probably not result in any overhead (in release mode, and most likely a function call and return in debug mode):

inline MyClass< int, double, int, char >* makeInstance_simple()
{
return makeInstance<int, double, int, char>();
}

Share this post


Link to post
Share on other sites
I like that last solution of yours. I'm not particularly concerned about the miniscule overhead that may or may not generate as I won't be calling the function more than once or twice in my program anyway. Thanks!

Share this post


Link to post
Share on other sites

I like Loki typelists...


template<typename TL> class MyClass
{
typedef typename Loki::TL::TypeAt<TL,0>::Result T;
typedef typename Loki::TL::TypeAt<TL,1>::Result U;
typedef typename Loki::TL::TypeAt<TL,2>::Result V;
typedef typename Loki::TL::TypeAt<TL,3>::Result W;

// ...
};

// the types you want
typedef LOKI_TYPELIST_4(int, double, int, char) types_t;

// instanciate
MyClass<types_t> fnar;

Share this post


Link to post
Share on other sites
Normally classes with complex templating will have similarly complex constructors, in which case you can rely on type inference in the helper function. For example, the standard library provides (this is not necessarily how it's implemented - I invoke the "as-if rule" here ;) )


namespace std {
template <typename T1, typename T2>
struct pair {
T1 first;
T2 second;
pair(const T1& x, const T2& y) : first(x), second(y) {}
// possibly some other functions I forgot?
};

template <typename T1, typename T2>
pair<T1, T2> make_pair(const T1& x, const T2& y) {
return pair<T1, T2>(x, y);
}

// Now calling code can do 'std::make_pair(foo, bar)' and not have to specify
// the type names.
}


(EDIT: But if that doesn't apply in your case, then NotAYakk and JohnBolton have the right idea. Happy hacking!)

[Edited by - Zahlman on June 7, 2006 3:15:53 PM]

Share this post


Link to post
Share on other sites
template < class T, class U, class V, class W > class MyClass
{

};

template < class T, class U, class V, class W >
MyClass< T, U, V, W >* makeInstance()
{
return new MyClass< T, U, V, W >;
}

MyClass< a, b, c, d >* my_makeInstance() {
return makeInstance<a, b, c, d>();
};

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
Yeah sorry, I just realized that I haven't correctly described my problem.

*** Source Snippet Removed ***

That's what I really want. Is it possible to make the makeInstance() function more easily accessible via some typedef magic?

How about this:

typedef MyClass< int, double, int, char > UseThis;

// Make an instance.
UseThis AnInstance;

template < class T, class U, class V, class W >
MyClass< T, U, V, W >* makeInstance()
{
return new MyClass< T, U, V, W >;
}

inline UseThis * makeUseThisInstance()
{
return makeInstance< int, double, int, char >();
}

UseThis * NewInstance = makeUseThisInstance();

Share this post


Link to post
Share on other sites
If your template parameters are POD types then you could also pass them as function parameters and let the template mechanism deduce the types like

template<class A, class B, class C>
my_class<A, B, C> *make_instance(A, B, C)
{
return new my_class<A, B, C>();
}

and then call this passing instances of POD data as an argument like
float f;
make_instance(f, f, f); // returns a my_class<float,float,float>*

for some situations this comes in handy.. it really depends on where you construct your object and how it fits into the code. dinkumware's stl implementation makes use of this a little bit.
again, if it fits in naturally into your code and how you use things then this is a fine solution, imo.

cheers,
simon

EDIT: i noticed, that's basically what Zahlman said..

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this