www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - this T / variadic template and interfaces

reply frame <frame86 live.com> writes:
Did not find this topic:

I have an interface and some wrapper classes that use it. The 
wrapper's methods should accept variadic arguments. The runtime 
should only work with the interface, trying casting to a wrapper 
is not an option, because it's a plugin design.

- defining a variadic template in wrapper does not work, because 
we are working with the interface only and compiler complains 
method is not callable with argument X

- defining a variadic template without body in interface causes 
linker errors, which makes sense somehow

- defining a variadic template with body in interface could work 
if the compiler would get the right "this" type but sadly, "this" 
refers to interface and also "this T" refers to interface too.

Is there any way to get this working? I know, I could use a known 
object to feed the arguments and use that instead - but I want to 
keep things simple as possible.
Oct 26 2020
next sibling parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 26 October 2020 at 11:14:47 UTC, frame wrote:
 Did not find this topic:

 I have an interface and some wrapper classes that use it. The 
 wrapper's methods should accept variadic arguments. The runtime 
 should only work with the interface, trying casting to a 
 wrapper is not an option, because it's a plugin design.

 - defining a variadic template in wrapper does not work, 
 because we are working with the interface only and compiler 
 complains method is not callable with argument X

 - defining a variadic template without body in interface causes 
 linker errors, which makes sense somehow

 - defining a variadic template with body in interface could 
 work if the compiler would get the right "this" type but sadly, 
 "this" refers to interface and also "this T" refers to 
 interface too.

 Is there any way to get this working? I know, I could use a 
 known object to feed the arguments and use that instead - but I 
 want to keep things simple as possible.
Templates can't be virtual, so even if they can be defined in an interface, you can't override them in a class that implements said interface - the implementation needs to be in the interface itself. This makes sense if you consider that the user of the interface has no knowledge of the types that implement it, and vice versa: the implementing class has no idea which instantiations to make, and the user has no idea which implementing classes to create instantiations for. Templates require that the user have full knowledge of the templates to be instantiated. There are some workarounds of sorts, but they depend heavily on what you're trying to achieve. Can you use an array of std.variant.Variant, for instance? -- Simen
Oct 26 2020
parent frame <frame86 live.com> writes:
On Monday, 26 October 2020 at 11:48:48 UTC, Simen Kjærås wrote:
 

 This makes sense if you consider that the user of the interface 
 has no knowledge of the types that implement it, and vice 
 versa: the implementing class has no idea which instantiations 
 to make, and the user has no idea which implementing classes to 
 create instantiations for. Templates require that the user have 
 full knowledge of the templates to be instantiated.

 There are some workarounds of sorts, but they depend heavily on 
 what you're trying to achieve. Can you use an array of 
 std.variant.Variant, for instance?

 --
   Simen
Yes, the user/coder does not know of other types by any chance. The interface must be used. Well I guess I let the interface do the variadic stuff and pass the argument as Variant[] to the wrapper in a new interface method. Thanks.
Oct 26 2020
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On Monday, 26 October 2020 at 11:14:47 UTC, frame wrote:

 Is there any way to get this working? I know, I could use a 
 known object to feed the arguments and use that instead - but I 
 want to keep things simple as possible.
As Simen mentioned, templates cannot be virtual. But you don't need to use a template, you can use a regular variadic method [1]. It's a bit more clunky to work with than template variadic functions. Or if all the arguments will be of the same type, you can use type safe variadic functions [2], which are easier to work with. [1] https://dlang.org/spec/function.html#d_style_variadic_functions [2] https://dlang.org/spec/function.html#typesafe_variadic_functions -- /Jacob Carlborg
Oct 26 2020
parent reply frame <frame86 live.com> writes:
On Monday, 26 October 2020 at 13:02:33 UTC, Jacob Carlborg wrote:
 On Monday, 26 October 2020 at 11:14:47 UTC, frame wrote:

 Is there any way to get this working? I know, I could use a 
 known object to feed the arguments and use that instead - but 
 I want to keep things simple as possible.
As Simen mentioned, templates cannot be virtual. But you don't need to use a template, you can use a regular variadic method [1]. It's a bit more clunky to work with than template variadic functions. Or if all the arguments will be of the same type, you can use type safe variadic functions [2], which are easier to work with. [1] https://dlang.org/spec/function.html#d_style_variadic_functions [2] https://dlang.org/spec/function.html#typesafe_variadic_functions -- /Jacob Carlborg
Hmm, a question of design. Is there also a convenient way to pass the arguments to a template or get a Variant[] from it?
Oct 27 2020
parent reply Jacob Carlborg <doob me.com> writes:
On Tuesday, 27 October 2020 at 09:40:33 UTC, frame wrote:

 Hmm, a question of design. Is there also a convenient way to 
 pass the arguments to a template or get a Variant[] from it?
Convenient, no not that I know of. You can use a type safe variadic function that takes Variant, if you want to end up with Variant[] anyway. It depends on how you want the API to look like. Here are some examples: void foo(...); void bar(Variant[] args ...); foo(3, "foo", 'a'); // pass in the arguments as is bar(Variant(3), Variant("foo"), Variant('a')); // need to wrap each argument in Variant The advantage of using the type safe variadic function is that all the arguments are bundle into one array, make it easier to work with. -- /Jacob Carlborg
Oct 27 2020
parent reply frame <frame86 live.com> writes:
On Tuesday, 27 October 2020 at 10:41:06 UTC, Jacob Carlborg wrote:
 On Tuesday, 27 October 2020 at 09:40:33 UTC, frame wrote:

 Hmm, a question of design. Is there also a convenient way to 
 pass the arguments to a template or get a Variant[] from it?
Convenient, no not that I know of. You can use a type safe variadic function that takes Variant, if you want to end up with Variant[] anyway. It depends on how you want the API to look like. Here are some examples: void foo(...); void bar(Variant[] args ...); foo(3, "foo", 'a'); // pass in the arguments as is bar(Variant(3), Variant("foo"), Variant('a')); // need to wrap each argument in Variant The advantage of using the type safe variadic function is that all the arguments are bundle into one array, make it easier to work with. -- /Jacob Carlborg
I tried the (...) thing - I ran into access violation by passing a slice like: if (_arguments[i] == typeid(ubyte[])) { auto foo = va_arg!(ubyte[])(_argptr); } The same is working with variadic template. I am missing something?
Oct 27 2020
parent frame <frame86 live.com> writes:
On Tuesday, 27 October 2020 at 11:30:53 UTC, frame wrote:
 On Tuesday, 27 October 2020 at 10:41:06 UTC, Jacob Carlborg 
 wrote:

 if (_arguments[i] == typeid(ubyte[])) {
   auto foo = va_arg!(ubyte[])(_argptr);
 }

 The same is working with variadic template. I am missing 
 something?
Never mind, I was squeezing the argument list through a delegate but the actual method - thus the pointer was 0.
Oct 27 2020