digitalmars.D - Concepts? Template specialization depending on class functions?
- Ben Phillips (25/25) Mar 02 2006 I have a question and a suggestion:
- Ben Phillips (15/40) Mar 02 2006 I should probably have clarified that a class would not have to inherit ...
- Ben Phillips (5/7) Mar 02 2006 From reading the docs it seems like I should be able to do this using "i...
- Oskar Linde (18/28) Mar 02 2006 I'm not fully sure of the syntax, but this seems to work:
- Ben Phillips (5/33) Mar 02 2006 Ah.. thanks! This helps a lot. You pointed out that your last method for...
- Walter Bright (4/7) Mar 02 2006 Concepts are an interesting idea. As far as I know, nobody has implement...
- Sean Kelly (67/75) Mar 02 2006 Now that static if is ignored for template expansion, concepts aren't as...
- Sean Kelly (5/11) Mar 02 2006 paste error, the above should not contain an assert. Also, my C++ style...
- Ben Phillips (4/11) Mar 02 2006 While this is true, if you have a large interface to check for compatabi...
- Sean Kelly (18/30) Mar 03 2006 Yup. I briefly considered private functions with aliases inside the
I have a question and a suggestion: Is it possible to determine whether a given class contains a specific member function? It would be useful to be able to create a template for classes that have certain functions without requiring the user to inherit from an interface. One idea I've heard is to use "concepts" (a possible extension to C++) where code would go as follows concept Collection(T) { bool add(T t); bool isEmpty(); .. } template doSomething(CollectionType : Collection) { void doSomething(CollectionType t) { ... } } This would allow the compiler to give a clearer error message to people who try to use the template with a class that doesn't fit the Collection concept. Instead of errors about undefined functions the user would be told something like "Error: T does not fit the Collection concept [and maybe list the missing functions'".
Mar 02 2006
In article <du751p$1imp$1 digitaldaemon.com>, Ben Phillips says...I have a question and a suggestion: Is it possible to determine whether a given class contains a specific member function? It would be useful to be able to create a template for classes that have certain functions without requiring the user to inherit from an interface. One idea I've heard is to use "concepts" (a possible extension to C++) where code would go as follows concept Collection(T) { bool add(T t); bool isEmpty(); .. } template doSomething(CollectionType : Collection) { void doSomething(CollectionType t) { ... } } This would allow the compiler to give a clearer error message to people who try to use the template with a class that doesn't fit the Collection concept. Instead of errors about undefined functions the user would be told something like "Error: T does not fit the Collection concept [and maybe list the missing functions'".I should probably have clarified that a class would not have to inherit from a concept to qualify for a template. It would only have to have functions (and possibly aliases) of the same names. Concepts would also only be used to help specialize templates. It would be illegal to do something like concept Queue { ... } void foo() { Queue q = new QueueClassThatFitsConcept(); // error, concepts aren't types and can't be instantiated. Use interfaces in this case } Also, most importantly, since concepts aren't types and classes that "fit" a concept don't inherit from them there is no virtual function overhead (actually a class doesn't even have to know the concepts it fits).
Mar 02 2006
In article <du751p$1imp$1 digitaldaemon.com>, Ben Phillips says...Is it possible to determine whether a given class contains a specific member function?From reading the docs it seems like I should be able to do this using "is", but the appropriate syntax is unclear and I can't seem to figure it out. Does "is" make it possible to test of a class has a certain member function and, if so, what is the correct syntax?
Mar 02 2006
Ben Phillips wrote:In article <du751p$1imp$1 digitaldaemon.com>, Ben Phillips says...I'm not fully sure of the syntax, but this seems to work: To test if a class T contains a method test: is(typeof(T.test) == function) Or conceptualized: template Testable(T) { const Testable = is(typeof(T.test) == function)); } One could wish that you could write something like: is(typeof(T.test) == int function(T)) To make sure that the function signature is OK, but this does not seem to work. Instead, the following works kind of but doesn't check the exact type of the arguments. To check if T contains a method with the signature similar to int test(int,int,int): is(typeof((new T).test(1,1,1)) == int) But will be true for e.g. a int test(real,real,real) too... /OskarIs it possible to determine whether a given class contains a specific member function?From reading the docs it seems like I should be able to do this using "is", but the appropriate syntax is unclear and I can't seem to figure it out. Does "is" make it possible to test of a class has a certain member function and, if so, what is the correct syntax?
Mar 02 2006
In article <du7sda$2kmq$1 digitaldaemon.com>, Oskar Linde says...Ben Phillips wrote:Ah.. thanks! This helps a lot. You pointed out that your last method for testing method signature and arguments can be slightly ambiguous, but I doubt this will pose a problem in most real world scenarios.In article <du751p$1imp$1 digitaldaemon.com>, Ben Phillips says...I'm not fully sure of the syntax, but this seems to work: To test if a class T contains a method test: is(typeof(T.test) == function) Or conceptualized: template Testable(T) { const Testable = is(typeof(T.test) == function)); } One could wish that you could write something like: is(typeof(T.test) == int function(T)) To make sure that the function signature is OK, but this does not seem to work. Instead, the following works kind of but doesn't check the exact type of the arguments. To check if T contains a method with the signature similar to int test(int,int,int): is(typeof((new T).test(1,1,1)) == int) But will be true for e.g. a int test(real,real,real) too... /OskarIs it possible to determine whether a given class contains a specific member function?From reading the docs it seems like I should be able to do this using "is", but the appropriate syntax is unclear and I can't seem to figure it out. Does "is" make it possible to test of a class has a certain member function and, if so, what is the correct syntax?
Mar 02 2006
"Ben Phillips" <Ben_member pathlink.com> wrote in message news:du751p$1imp$1 digitaldaemon.com...One idea I've heard is to use "concepts" (a possible extension to C++) where code would go as followsConcepts are an interesting idea. As far as I know, nobody has implemented it for C++ so nobody knows if it really works or not.
Mar 02 2006
Walter Bright wrote:"Ben Phillips" <Ben_member pathlink.com> wrote in message news:du751p$1imp$1 digitaldaemon.com...Now that static if is ignored for template expansion, concepts aren't as necessary as they once were. For example, this is how I'd have implemented concepts in D before, which is fairly close to how it would be done in C++: struct DoesNiftyThingA {} struct DoesNiftyThingB {} struct DoesntDoAnything {} template testFeatures( T ) { static if( /* test for A */ ) alias DoesNiftyThingA testFeatures; else static if( /* test for B */ ) alias DoesNiftyThingB testFeatures; else alias DoesntDoAnything testFeatures; } // specialization for A template conceptFn( T, T1 : DoesNiftyThingA = testFeatures!(T) ) { static assert( is(testFeatures!(T) == DoesNiftyThingA ); void conceptFn() {} } // specialization for B template conceptFn( T, T1 : DoesNiftyThingB = testFeatures!(T) ) { static assert( is(testFeatures!(T) == DoesNiftyThingB ); void conceptFn() {} } // default implementation template conceptFn( T ) { static assert( is(testFeatures!(T) == DoesNiftyThingB ); void conceptFn() {} } But using the template parameter list is unwieldy and error-prone (this the static asserts). However, the equivalent now could be: template conceptFn( T ) { static if( /* test for A */ ) void conceptFn() {} else static if( /* test for B */ ) void conceptFn() {} else void conceptFn() {} } And pragmas make it fairly easy to provide meaningful error messages if there is no default: template conceptFn( T ) { static if( /* test for A */ ) void conceptFn() {} else static if( /* test for B */ ) void conceptFn() {} else { pragma( msg, "conceptFn is not defined for this type." ); static assert( false ); } } Coupled with Don's template string magic, it should be fairly simple to improve the error message to include the supplied type name, etc. So... while I think concepts may still be nice to have, I'm not sure there's a pressing need for them any longer. In fact, I think I'm going to go back and rewrite my template code to use the "static if" method above, as most of it still uses the old C++ style. SeanOne idea I've heard is to use "concepts" (a possible extension to C++) where code would go as followsConcepts are an interesting idea. As far as I know, nobody has implemented it for C++ so nobody knows if it really works or not.
Mar 02 2006
Sean Kelly wrote:// default implementation template conceptFn( T ) { static assert( is(testFeatures!(T) == DoesNiftyThingB ); void conceptFn() {} }paste error, the above should not contain an assert. Also, my C++ style example even used "static if" in the "new" way. A true representation would actually be slightly longer/more complex. Sean
Mar 02 2006
In article <du7qud$2ji7$1 digitaldaemon.com>, Sean Kelly says...Coupled with Don's template string magic, it should be fairly simple to improve the error message to include the supplied type name, etc. So... while I think concepts may still be nice to have, I'm not sure there's a pressing need for them any longer. In fact, I think I'm going to go back and rewrite my template code to use the "static if" method above, as most of it still uses the old C++ style. SeanWhile this is true, if you have a large interface to check for compatability with, template code can still become messy.
Mar 02 2006
Ben Phillips wrote:In article <du7qud$2ji7$1 digitaldaemon.com>, Sean Kelly says...Yup. I briefly considered private functions with aliases inside the static if: private implA() {} private implB() {} template conceptFn( T ) { static if( /* supports A */ ) alias implA conceptFn; else if( /* supports B */ ) alias implB conceptFn; else { pragma( msg, "Not supported." ); static assert( false ); } } But I ultimately decided to simply format and comment things in a way that was as readable as possible. SeanCoupled with Don's template string magic, it should be fairly simple to improve the error message to include the supplied type name, etc. So... while I think concepts may still be nice to have, I'm not sure there's a pressing need for them any longer. In fact, I think I'm going to go back and rewrite my template code to use the "static if" method above, as most of it still uses the old C++ style.While this is true, if you have a large interface to check for compatability with, template code can still become messy.
Mar 03 2006