www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Templates ~ best way to limit types?

reply "Kris" <fu bar.com> writes:
class MyTemplate(T)
{
        static if (is (T == char)) {}
        else
        static if (is (T == wchar)) {}
        else
        static if (is (T == wchar)) {}
        else
           {
           pragma (msg, "Template type must be char, wchar, or dchar");
           static assert(0);
           }

    // ...
}

what is the best (most succinct?) way to limit the T type? What I'm looking 
for is a nice compile time message saying "type must be x, y, or z" ...

The current approach is noted above, but I imagine/hope it could be a lot 
better?

Also, is there a better way to halt the compiler? So many error messages are 
emitted that it's quite hard to see the pragma message :-)

Thanks;
Dec 11 2005
parent reply Don Clugston <dac nospam.com.au> writes:
Kris wrote:
 class MyTemplate(T)
 {
         static if (is (T == char)) {}
         else
         static if (is (T == wchar)) {}
         else
         static if (is (T == wchar)) {}
         else
            {
            pragma (msg, "Template type must be char, wchar, or dchar");
            static assert(0);
            }
 
     // ...
 }
 
 what is the best (most succinct?) way to limit the T type? What I'm looking 
 for is a nice compile time message saying "type must be x, y, or z" ...

Hmm, sounds like the 'constraints' proposal being discussed for C++0x. Right now, the best I can think of is something like: template isInList(T, A, B, C) { static if (is (T==A)) const bool isInList=true; else static if (is(T==B)) const bool isInList=true; else static if (is(T==C)) const bool isInList=true; else const bool isInList=false; } class MyTemplate(T) { static assert(isInList(T, char, wchar, dchar)); } obviously with overloads of isInList() for different numbers of arguments. The preprocessor strikes again, until we get varag templates...
 Also, is there a better way to halt the compiler? So many error messages are 
 emitted that it's quite hard to see the pragma message :-)

I think that static assert() should halt compilation, just as assert() halts at runtime. Do you see any problems with that? (I've had terrible problems with a static assert in a recursive function, you get the same error two million times).
Dec 12 2005
next sibling parent kris <fu bar.org> writes:
Don Clugston wrote:
 Kris wrote:
 
 class MyTemplate(T)
 {
         static if (is (T == char)) {}
         else
         static if (is (T == wchar)) {}
         else
         static if (is (T == wchar)) {}
         else
            {
            pragma (msg, "Template type must be char, wchar, or dchar");
            static assert(0);
            }

     // ...
 }

 what is the best (most succinct?) way to limit the T type? What I'm 
 looking for is a nice compile time message saying "type must be x, y, 
 or z" ...

Hmm, sounds like the 'constraints' proposal being discussed for C++0x. Right now, the best I can think of is something like: template isInList(T, A, B, C) { static if (is (T==A)) const bool isInList=true; else static if (is(T==B)) const bool isInList=true; else static if (is(T==C)) const bool isInList=true; else const bool isInList=false; } class MyTemplate(T) { static assert(isInList(T, char, wchar, dchar)); } obviously with overloads of isInList() for different numbers of arguments. The preprocessor strikes again, until we get varag templates...
 Also, is there a better way to halt the compiler? So many error 
 messages are emitted that it's quite hard to see the pragma message :-)

I think that static assert() should halt compilation, just as assert() halts at runtime. Do you see any problems with that? (I've had terrible problems with a static assert in a recursive function, you get the same error two million times).

Thanks Don! That looks more useful. Static assert() does halt, but not quickly enough I'm afraid ~ it just adds another little warning to the sea washing over the console :)
Dec 12 2005
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Don Clugston wrote:
 Kris wrote:
 class MyTemplate(T)
 {
         static if (is (T == char)) {}
         else
         static if (is (T == wchar)) {}
         else
         static if (is (T == wchar)) {}
         else
            {
            pragma (msg, "Template type must be char, wchar, or dchar");
            static assert(0);
            }

     // ...
 }

 what is the best (most succinct?) way to limit the T type? What I'm 
 looking for is a nice compile time message saying "type must be x, y, 
 or z" ...

Hmm, sounds like the 'constraints' proposal being discussed for C++0x. Right now, the best I can think of is something like: template isInList(T, A, B, C) { static if (is (T==A)) const bool isInList=true; else static if (is(T==B)) const bool isInList=true; else static if (is(T==C)) const bool isInList=true; else const bool isInList=false; } class MyTemplate(T) { static assert(isInList(T, char, wchar, dchar)); } obviously with overloads of isInList() for different numbers of arguments. The preprocessor strikes again, until we get varag templates...

You can also do something like this: template isValidType( T ) { const bit isValidType = is(T:char) || is(T:wchar); } template doSomething( T, bit vt : true = isValidType!(T) ) { // make sure the user isn't trying to trick us static assert( isValidType!(T) ); ... } Sean
Dec 12 2005
parent reply "Kris" <fu bar.com> writes:
Thx Sean;

What is the difference between "is (T:char)" and "is (T == char)" ? I had 
the impression there was one, but can't find it now ...



"Sean Kelly" <sean f4.ca> wrote in message 
news:dnklve$2cqj$1 digitaldaemon.com...
 Don Clugston wrote:
 Kris wrote:
 class MyTemplate(T)
 {
         static if (is (T == char)) {}
         else
         static if (is (T == wchar)) {}
         else
         static if (is (T == wchar)) {}
         else
            {
            pragma (msg, "Template type must be char, wchar, or dchar");
            static assert(0);
            }

     // ...
 }

 what is the best (most succinct?) way to limit the T type? What I'm 
 looking for is a nice compile time message saying "type must be x, y, or 
 z" ...

Hmm, sounds like the 'constraints' proposal being discussed for C++0x. Right now, the best I can think of is something like: template isInList(T, A, B, C) { static if (is (T==A)) const bool isInList=true; else static if (is(T==B)) const bool isInList=true; else static if (is(T==C)) const bool isInList=true; else const bool isInList=false; } class MyTemplate(T) { static assert(isInList(T, char, wchar, dchar)); } obviously with overloads of isInList() for different numbers of arguments. The preprocessor strikes again, until we get varag templates...

You can also do something like this: template isValidType( T ) { const bit isValidType = is(T:char) || is(T:wchar); } template doSomething( T, bit vt : true = isValidType!(T) ) { // make sure the user isn't trying to trick us static assert( isValidType!(T) ); ... } Sean

Dec 12 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Kris wrote:
 Thx Sean;
 
 What is the difference between "is (T:char)" and "is (T == char)" ? I had 
 the impression there was one, but can't find it now ...

You probably want "T==char." IIRC, "T:char" requires that T be convertible to char while "T==char" requires that T be the type 'char'. I really need to fix this for std.atomic as well :-) Sean
Dec 12 2005
parent Sean Kelly <sean f4.ca> writes:
Sean Kelly wrote:
 Kris wrote:
 Thx Sean;

 What is the difference between "is (T:char)" and "is (T == char)" ? I 
 had the impression there was one, but can't find it now ...

You probably want "T==char." IIRC, "T:char" requires that T be convertible to char while "T==char" requires that T be the type 'char'. I really need to fix this for std.atomic as well :-)

Oh, the reason I suggested my method is that it should just not instantiate the template at all if the type doesn't match, which should provide more useful error messages. I do like Don's pseudo typelist approach for over my isValidType template, so the two could be combined as well. Sean
Dec 12 2005
prev sibling parent reply Oskar Linde <oskar.lindeREM OVEgmail.com> writes:
Kris wrote:
 Thx Sean;
 
 What is the difference between "is (T:char)" and "is (T == char)" ? I had 
 the impression there was one, but can't find it now ...

As far as I have understood, is (T:char) is true if T is implicitly convertible to char, is (T == char) is true only for T == char i.e. is (int:char) is true, while is (int == char) is false. /Oskar
Dec 12 2005
parent "Kris" <fu bar.com> writes:
Thx!

"Oskar Linde" <oskar.lindeREM OVEgmail.com> wrote in message 
news:dnknih$2f3j$1 digitaldaemon.com...
 Kris wrote:
 Thx Sean;

 What is the difference between "is (T:char)" and "is (T == char)" ? I had 
 the impression there was one, but can't find it now ...

As far as I have understood, is (T:char) is true if T is implicitly convertible to char, is (T == char) is true only for T == char i.e. is (int:char) is true, while is (int == char) is false. /Oskar

Dec 12 2005