Using templates with interfaces

Nicholas Wilson via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jun 25 06:04:32 PDT 2017


On Sunday, 25 June 2017 at 11:39:27 UTC, Andrew Chapman wrote:
> Hi guys, I'm a little confused as to whether D supports 
> interfaces with templates.  I can compile OK, but linking 
> reports an error like this:
>
> Error 42: Symbol Undefined 
> _D12relationaldb10interfaces21RÇëÜDBIÇêÿ35__T7loadRowTS6prefix÷6P¶ZÇêáMFAyaAS3std7variant18Çâ└8VÇåìNVki20ZÇëÅZÇûð
>
> Essentially my desired interface looks like this:
>
> interface RelationalDBInterface {
>     public T loadRow(T)(string sql, Variant[] params);
> }
>
> An example implementation:
>
> public T loadRow(T)(string sql, Variant[] params)
> {
> 	Prepared prepared = prepare(this.conn, sql);
> 	prepared.setArgs(params);
>
> 	auto row = prepared.queryRow();
>
> 	if (row.isNull()) {
> 	    throw new Exception(this.classID ~ "::loadRow - Query 
> returned an empty row");
> 	}
>
> 	T item;
> 	return row.toStruct!T(item);
> }
>
> And I would try to call it like this:
>
> auto user = this.loadRow!User(sql, params);
>
> Is it possible, or do I need to rethink the solution?  The idea 
> is to pass around a RelationalDBInterface so I can later switch 
> from MySQL to Postgres or SQLite or whatever.

You cannot have unimplemented templates in interfaces (where 
would they go in the virtual function table?), just return a 
variant.
Implementations of interfaces must be classes not free functions
so

class MyDB : IRelationalDB
{
     // implementation ...
}

which you then need to create a instance of

auto mydb = MyDB(...); // connection
auto user = mydb.loadRow!User(sql, params);

'this' is only valid inside an aggregate (struct or class).




More information about the Digitalmars-d-learn mailing list