Archived

This topic is now archived and is closed to further replies.

aboeing

templates: A<B<C>,C>

Recommended Posts

Hi, Im just wondering if there is some way to enforce that two template parameters are the same, so if you have A < B < C > , D >, is there some way to make sure C == D? eg:
class A {};
class B {};
template <typename AB> 
class X {};
template <typename AB>
class Y {};

template<typename X, typename AB> 
class Z:public X {
 Y<AB>* dosomething();
}

//inmain:

Z<Y<A>,A> variable_ok;
Z<Y<A>,B> variable_should_not_be_ok;
Im using VC6, and would like it to be a compile-time assertion if possible. Thanks. edit: fixed so " < "'s show up [edited by - aboeing on October 21, 2003 12:31:59 AM]

Share this post


Link to post
Share on other sites
Probably not. Template arguments must be completely specified types; and once templated types are completely specified, their template arguments only exist as part of the type.

What are you trying to do here? There may be another way.

EDIT: waitasec. Do you want your A to be implementable with ANY B, or with a specific B?


How appropriate. You fight like a cow.

[edited by - sneftel on October 21, 2003 12:40:30 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by Sneftel
EDIT: waitasec. Do you want your A to be implementable with ANY B, or with a specific B?


Uh, not sure what you mean here. A and B should have anything to do with each other. think of them as A1 and A2 if that makes it clearer..

The specific thing im trying to do is to make a pluggable factory, which has a specifyable selection mechanism. (so i can register lots of objects, and different factories will create different objects according to which one is most appropriate). but different selection mechanisms will require different registration data structures, and also each factoryobject will need a diferent ''register'' function according to which data structure is being used.

eg:

#define STATIC_CHECK(expr) {char unnamed[(expr) ? 1 : 0];}

class DataStructure {
public:
void Register(int x) {};
int x;
};

class ADifferentDataStructure {
public:
void Register(char *sz) {};
char *sz;
};

template <typename DS>
class SelectionPolicy {
public:
void UpdateRegistry() {};
DS structure;
};

template <typename DS>
class Object : public DS {
};

template <typename SP, typename DS>
class Factory : public SP {
public:
Object<DS>* CreateObject() {
//STATIC_CHECK( that DS and SP<DS> are the same somehow);

return new Object<DS>;
};
};

//inmain:

//this is okay:

Factory<SelectionPolicy<DataStructure>,DataStructure> f;
f.CreateObject();
//this is evil:

Factory<SelectionPolicy<ADifferentDataStructure>,DataStructure> f;
f.CreateObject();


The simplest solution I can think of is just to make one big datastrucutre class and then only use the bits of it that i need for different selection policys, but then this isn''t as flexible as i would like it to be, plus lots more typeing to register functions. =/

Does this make sense?

Share this post


Link to post
Share on other sites
Darnit, aboeing, quit making me goof off.

You can do it if you''re willing to encode the template parameter into B (here represented by Foo):


template<typename T1, typename T2>
class TypeEqualityChecker;

template<typename T>
class TypeEqualityChecker<T, T>
{
};

template<typename T>
class Foo
{
public:
typedef T myArg;
};

template<typename T1, typename T2>
class Bar
{
TypeEqualityChecker<typename T1::myArg, T2> checker;
};

int main()
{
Bar<Foo<int>, int> asdf; // fine

Bar<Foo<int>, double> jklsemicolon; // causes a funky error

}



How appropriate. You fight like a cow.

Share this post


Link to post
Share on other sites
quote:
Original post by aboeing
Hi, Im just wondering if there is some way to enforce that two template parameters are the same,
so if you have A < B < C > , D >, is there some way to make sure C == D?


If you wish, you could always do the following, for example

template<template<typename X> class Y, typename Z>
class A
{
...
};

Where the template parameter Y takes a class with a single template parameter, which you can use in the template class as

Y<Z>



[edited by - dot on October 22, 2003 2:42:36 AM]

Share this post


Link to post
Share on other sites
Darnit, aboeing, quit making me goof off.
heh Sorry But thanks for answering all my questions

That looks exactly like what I want, but im not sure how your code works, if you have time, could you explain it? or point me to a resource which will? Thanks!

this:
template
class TypeEqualityChecker;
template
class TypeEqualityChecker
{};
is what im not really understanding..(the second one basically)

re:dot:interesting, I will have to try it when I get home. (im not sure if VC6 supports that..)

Share this post


Link to post
Share on other sites
Neither suggestion will work with MSVC6, as i suspected, VC6 does not support nested templates:
(error C2954: template definitions cannot nest)

and for Sneftel''s suggestiong I get (on the class TypeEqualityChecker {}; line) :

error C2989: ''TypeEqualityChecker'' : template class has already been defined as a non-template class

any other suggestions?

Share this post


Link to post
Share on other sites
Oops, yeah. More importantly, VC6 also doesn''t do partial template instantiation, which is what my TypeEqualityChecker does (it only has a version of TypeEqualityChecker for any two equal template arguments; another combination would produce an error). Um..... I think you''re kind of SOL here. VC6''s templates are for crap.


How appropriate. You fight like a cow.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You want compile time intrensics. You can find a boost implementation here. Under template metaprogramming->traits.

http://www.boost.org/

It will allow you to determine if 2 templated params are the same etc.. at compile time.

-ddn

Share this post


Link to post
Share on other sites
I did a variant on Sneftels, but with explicit specialization. I have no idea if it will work in 6.0 (uninstalled it). Anyway, it might be worth a try:

#include <loki/static_check.h>

template <typename T1, typename T2>
class TypeEqualType
{
template <typename T1, typename T2>
struct TypeTester
{
enum {Result = false};
};

template <>
struct TypeTester<T1, T1>
{
enum {Result = true};
};

public:

enum {Result = TypeTester<T1,T2>::Result};

};

int main()
{
STATIC_CHECK( (TypeEqualType<int, int>::Result), NOT_SAME_TYPE );
STATIC_CHECK( (TypeEqualType<int, float>::Result), NOT_SAME_TYPE );
}

Edit: didn't see AP's post about boost. Probably a better choice.

[edited by - Matsen on October 22, 2003 3:56:43 PM]

Share this post


Link to post
Share on other sites
Thanks for the help guys!
Unfortunately the boost library''s implementation also relies on partial template specialization, so thanks to matsen for providing a solution that''ll work with VC6!

Cheers

Share this post


Link to post
Share on other sites