Jump to page: 1 2
Thread overview
Template Question
Apr 14, 2008
Mike Parker
Apr 14, 2008
Bill Baxter
Apr 15, 2008
Mike Parker
Apr 15, 2008
Bill Baxter
Apr 15, 2008
Mike Parker
Apr 15, 2008
Mike Parker
Apr 15, 2008
Bill Baxter
Apr 15, 2008
Bill Baxter
Apr 15, 2008
Mike Parker
Apr 15, 2008
Bill Baxter
Apr 15, 2008
Bill Baxter
Apr 15, 2008
Mike Parker
Apr 14, 2008
BCS
Apr 15, 2008
Mike Parker
Apr 15, 2008
Jakob
April 14, 2008
I've not worked much with templates in any language beyond the basics. Right now, I've got a problem that I've solved, but for which I'm looking a different solution.

What I have is a templated interface like so:

interface Foo(T)
{
    void init(T);
    void term();
    void blah();
    void bleh();
}

Then I have a Templated manager class intended to work with differently parameterized Foos:

class Manager(U)
{
    ...
}

The issue is that I want to make sure that Manager is instantiated with Foos without it knowing what the T in Foo is. This obviously doesn't work:

class Manager(U : Foo)
{
}

One way to solve the problem is to de-templatize Foo and create a new interface like so:

interface FooInit
{
}

interface Foo
{
   void init(FooInit fi);
}

I don't like that too much, though, since the parameters will always be PODs, so I'd prefer to use structs and not classes for them. The solution I've come up with, based on my limited knowledge, is to check that the parameter U for the manager implements all of the functions required by the Foo interface:

class Manager(U)
{
    static this()
    {
        static if(!is(typeof(&U.init)) && !is(typeof(&U.term))
                  && !is(typeof(&U.blah)) & !is(typeof(&U.bleh)));
    }
}

This works fine for my purposes, even though it allows any type that implements these methods, regardless of whether or not it implements Foo.

I'm curious if there is another way to do this, particularly some way to make sure that Manager only accepts Foo implementations without knowing how they are parameterized.
April 14, 2008
Mike Parker wrote:
> I've not worked much with templates in any language beyond the basics. Right now, I've got a problem that I've solved, but for which I'm looking a different solution.
> 
> What I have is a templated interface like so:
> 
> interface Foo(T)
> {
>     void init(T);
>     void term();
>     void blah();
>     void bleh();
> }
> 
> Then I have a Templated manager class intended to work with differently parameterized Foos:
> 
> class Manager(U)
> {
>     ...
> }
> 
> The issue is that I want to make sure that Manager is instantiated with Foos without it knowing what the T in Foo is. This obviously doesn't work:
> 
> class Manager(U : Foo)
> {
> }

I think there is a variation of that which is supposed to work:

class Manager(U : Foo!(T), T)
{
}

I'm not sure if it does in practice or not, though.


--bb
April 14, 2008
Mike Parker wrote:
> I've not worked much with templates in any language beyond the basics. Right now, I've got a problem that I've solved, but for which I'm looking a different solution.
> 
> What I have is a templated interface like so:
> 
> interface Foo(T)
> {
>     void init(T);
>     void term();
>     void blah();
>     void bleh();
> }
> 

quick-n-dirty (and untested)

interface FooBase{}
interface Foo(T) : FooBase
{
    void init(T);
    void term();
    void blah();
    void bleh();
}

then throw this in somewhere:

static assert(is(T:FooBase));
April 15, 2008
Bill Baxter wrote:
> Mike Parker wrote:
>> I've not worked much with templates in any language beyond the basics. Right now, I've got a problem that I've solved, but for which I'm looking a different solution.
>>
>> What I have is a templated interface like so:
>>
>> interface Foo(T)
>> {
>>     void init(T);
>>     void term();
>>     void blah();
>>     void bleh();
>> }
>>
>> Then I have a Templated manager class intended to work with differently parameterized Foos:
>>
>> class Manager(U)
>> {
>>     ...
>> }
>>
>> The issue is that I want to make sure that Manager is instantiated with Foos without it knowing what the T in Foo is. This obviously doesn't work:
>>
>> class Manager(U : Foo)
>> {
>> }
> 
> I think there is a variation of that which is supposed to work:
> 
> class Manager(U : Foo!(T), T)
> {
> }
> 
> I'm not sure if it does in practice or not, though.
> 
> 

Unfortunately, it doesn't.
April 15, 2008
BCS wrote:
> Mike Parker wrote:
>> I've not worked much with templates in any language beyond the basics. Right now, I've got a problem that I've solved, but for which I'm looking a different solution.
>>
>> What I have is a templated interface like so:
>>
>> interface Foo(T)
>> {
>>     void init(T);
>>     void term();
>>     void blah();
>>     void bleh();
>> }
>>
> 
> quick-n-dirty (and untested)
> 
> interface FooBase{}
> interface Foo(T) : FooBase
> {
>     void init(T);
>     void term();
>     void blah();
>     void bleh();
> }
> 
> then throw this in somewhere:
> 
> static assert(is(T:FooBase));

Good idea. And it would be perfect if I could hide FooBase inside the module, but I recall reading somewhere that the compiler doesn't respect private class and interface declarations. And a quick test proves it.
April 15, 2008
Mike Parker wrote:
> Bill Baxter wrote:
>> Mike Parker wrote:
>>> I've not worked much with templates in any language beyond the basics. Right now, I've got a problem that I've solved, but for which I'm looking a different solution.
>>>
>>> What I have is a templated interface like so:
>>>
>>> interface Foo(T)
>>> {
>>>     void init(T);
>>>     void term();
>>>     void blah();
>>>     void bleh();
>>> }
>>>
>>> Then I have a Templated manager class intended to work with differently parameterized Foos:
>>>
>>> class Manager(U)
>>> {
>>>     ...
>>> }
>>>
>>> The issue is that I want to make sure that Manager is instantiated with Foos without it knowing what the T in Foo is. This obviously doesn't work:
>>>
>>> class Manager(U : Foo)
>>> {
>>> }
>>
>> I think there is a variation of that which is supposed to work:
>>
>> class Manager(U : Foo!(T), T)
>> {
>> }
>>
>> I'm not sure if it does in practice or not, though.
>>
>>
> 
> Unfortunately, it doesn't.

I keep forgetting you don't get any type deduction with class templates.
So maybe would work if you are explicit about both arguments.  But that kind of defeats the purpose.

Yeh, so I guess you just have to settle for

class Manager(U /* : Foo!(T) */)
{
   static if (is(U T_ : Foo!(T_))) {
      alias T_ T;
   }
   else {
      static assert(false, "U must be a Foo!(T) for some T");
   }
}

--bb
April 15, 2008
Bill Baxter wrote:
> Mike Parker wrote:
>> Bill Baxter wrote:
>>> Mike Parker wrote:
>>>> I've not worked much with templates in any language beyond the basics. Right now, I've got a problem that I've solved, but for which I'm looking a different solution.
>>>>
>>>> What I have is a templated interface like so:
>>>>
>>>> interface Foo(T)
>>>> {
>>>>     void init(T);
>>>>     void term();
>>>>     void blah();
>>>>     void bleh();
>>>> }
>>>>
>>>> Then I have a Templated manager class intended to work with differently parameterized Foos:
>>>>
>>>> class Manager(U)
>>>> {
>>>>     ...
>>>> }
>>>>
>>>> The issue is that I want to make sure that Manager is instantiated with Foos without it knowing what the T in Foo is. This obviously doesn't work:
>>>>
>>>> class Manager(U : Foo)
>>>> {
>>>> }
>>>
>>> I think there is a variation of that which is supposed to work:
>>>
>>> class Manager(U : Foo!(T), T)
>>> {
>>> }
>>>
>>> I'm not sure if it does in practice or not, though.
>>>
>>>
>>
>> Unfortunately, it doesn't.
> 
> I keep forgetting you don't get any type deduction with class templates.
> So maybe would work if you are explicit about both arguments.  But that kind of defeats the purpose.
> 
> Yeh, so I guess you just have to settle for
> 
> class Manager(U /* : Foo!(T) */)
> {
>    static if (is(U T_ : Foo!(T_))) {
>       alias T_ T;
>    }
>    else {
>       static assert(false, "U must be a Foo!(T) for some T");
>    }
> }
> 
> --bb

This is exactly what I was looking for. I don't understand it, but it works.
April 15, 2008
Mike Parker wrote:
> Bill Baxter wrote:
>> Mike Parker wrote:
>>> Bill Baxter wrote:
>>>> Mike Parker wrote:

> 
> This is exactly what I was looking for. I don't understand it, but it works.

Actually, it doesn't work.
April 15, 2008
Mike Parker wrote:
> Mike Parker wrote:
>> Bill Baxter wrote:
>>> Mike Parker wrote:
>>>> Bill Baxter wrote:
>>>>> Mike Parker wrote:
> 
>>
>> This is exactly what I was looking for. I don't understand it, but it works.
> 
> Actually, it doesn't work.

Yeh, it's a bug then.

I'll file it.


--bb
April 15, 2008
Mike Parker wrote:
> Mike Parker wrote:
>> Bill Baxter wrote:
>>> Mike Parker wrote:
>>>> Bill Baxter wrote:
>>>>> Mike Parker wrote:
> 
>>
>> This is exactly what I was looking for. I don't understand it, but it works.
> 
> Actually, it doesn't work.

Ok, so in that case...
I think you can put an alias for the type inside an interface, and use that to work around:

interface Foo(T)
{
    alias T TheType;
    void init(T);
}

...
 static if ( is(U : Foo!(U.TheType)) ) {
   ...
  }

That seems to work.

--bb
« First   ‹ Prev
1 2