Thread overview | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 06, 2013 Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Suppose, in c++ i've got a variadic template function F, and i want to convert all the arguments in some individual manner by function conv and pass all the converted arguments as a variadic list to another variadic template function G. Then i just do the following: template<typename T> struct R; template<typename T> R<T>::Type conv(T&& val); template<typename ... Args> void F(Args&& ... args) { G(conv(std::forward<Args>(args))...); } Is there any way to do the same kind of thing in D? I couldn't find any unpacking operator or a library function to do so... The problem is that i have to pass converted lits to a C-like variadic function, for example printf, so it would be like: template<typename T> struct R; template<typename T> R<T>::Type conv(T&& val); template<typename ... Args> void MyPrintf(const char * format, Args&& ... args) { printf(convFormat(format), conv(std::forward<Args>(args))...); } I hope, my point is clear enough. |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Max Strakhov | On 07/05/2013 05:41 PM, Max Strakhov wrote: > Suppose, in c++ i've got a variadic template function F, and i want to > convert all the arguments in some individual manner by function conv and > pass all the converted arguments as a variadic list to another variadic > template function G. > Then i just do the following: > > template<typename T> > struct R; > > template<typename T> > R<T>::Type conv(T&& val); > > template<typename ... Args> > void F(Args&& ... args) { > G(conv(std::forward<Args>(args))...); > } > > Is there any way to do the same kind of thing in D? I couldn't find any > unpacking operator or a library function to do so... > The problem is that i have to pass converted lits to a C-like variadic > function, for example printf, so it would be like: > > template<typename T> > struct R; > > template<typename T> > R<T>::Type conv(T&& val); > > template<typename ... Args> > void MyPrintf(const char * format, Args&& ... args) { > printf(convFormat(format), conv(std::forward<Args>(args))...); > } > > I hope, my point is clear enough. Here is one that works: import core.stdc.stdio; import std.string; string convFormat(string s) { return s ~ '\n'; } void myPrintf(T...)(string s, T args) { printf(convFormat(s).toStringz, args); } void main() { myPrintf("format %d %f %c %s", 42, 1.5, 'a', "hello".toStringz); } Ideally, the caller of MyPrintf should not have to call toStringz on "hello", because myPrintf is a proper D function. However, I don't know how to manipulate args to call toStringz on string arguments. More information is at http://dlang.org/template.html#TemplateTupleParameter Ali |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On 07/05/2013 06:35 PM, Ali Çehreli wrote: > More information is at > > http://dlang.org/template.html#TemplateTupleParameter And the definitive document on templates is the following: https://github.com/PhilippeSigaud/D-templates-tutorial Ali |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Max Strakhov | On 07/06/13 02:41, Max Strakhov wrote: > Suppose, in c++ i've got a variadic template function F, and i want to convert all the arguments in some individual manner by function conv and pass all the converted arguments as a variadic list to another variadic template function G. http://forum.dlang.org/thread/yiougbmcegjlsrynlvyt@forum.dlang.org?page=2#post-mailman.1205.1371553020.13711.digitalmars-d-learn:40puremagic.com artur |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Saturday, 6 July 2013 at 01:35:28 UTC, Ali Çehreli wrote: > On 07/05/2013 05:41 PM, Max Strakhov wrote: > Here is one that works: > > import core.stdc.stdio; > import std.string; > > string convFormat(string s) > { > return s ~ '\n'; > } > > void myPrintf(T...)(string s, T args) > { > printf(convFormat(s).toStringz, args); > } > > void main() > { > myPrintf("format %d %f %c %s", 42, 1.5, 'a', "hello".toStringz); > } You only converted the format string with was not in the question. I need to convert all args by a template function, but your example is actually better than mine. Suppose, i want my own string representation of primitive types, then in c++ i would write those two functions: convFormat("format %d %f %c %s") -> std::string("format %s %s %s %s") conv(42) -> std::string("int(42)") conv(1.5)-> std::string("float(1.5)") etc. and the resulting printf: template<typename ... Args> void myPrintf(const char * format, Args&& ... args) { printf(convFormat(format).c_str(), conv(std::forward<Args>(args)).c_str()...); } And that would do the job. Can i somehow do the same thing in D? |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | Artur, if i use your solution like printf("...", ForEach!(val => conv(val).c_str())(values).tuple); Than i would get a crash, because all the tuple elements would be char*'s, pointing to already freed memory, as std::string's destructor gets called each time right after alias function exits. Ths is what c++ unpacking operator for: i actually return a packed list of std::string's, apply .c_str() to each and than unpack the list to current context. |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Max Strakhov | On 07/06/13 14:21, Max Strakhov wrote:
> Artur, if i use your solution like
>
> printf("...", ForEach!(val => conv(val).c_str())(values).tuple);
>
> Than i would get a crash, because all the tuple elements would be char*'s, pointing to already freed memory, as std::string's destructor gets called each time right after alias function exits. Ths is what c++ unpacking operator for: i actually return a packed list of std::string's, apply .c_str() to each and than unpack the list to current context.
Can you show some simple code that exhibits the problem?
artur
|
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Artur Skawina | Thanx for all your help, i just solved the problem with mixins like this: string res = ""; for(i, rev v; args) res ~= string.format(", f(args[%d]).val()"); mixin("return G(" ~ res ~ ");"); Only without any actual looping and variables, so compiler could deal with it. |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to Max Strakhov | On Saturday, 6 July 2013 at 16:15:52 UTC, Max Strakhov wrote: > Thanx for all your help, i just solved the problem with mixins like this: > > string res = ""; > for(i, rev v; args) > res ~= string.format(", f(args[%d]).val()"); > mixin("return G(" ~ res ~ ");"); > > Only without any actual looping and variables, so compiler could deal with it. printf("...", ForEach!(val => conv(val).c_str())(values).tuple); ...would have done exactly the same as C++: printf("...", conv(values).c_str()...); ...does (barring it makes a temporary struct which holds one field for each of those converted const char pointers, but the compiler can optimize it away). |
July 06, 2013 Re: Variadic template arguments unpacking | ||||
---|---|---|---|---|
| ||||
Posted in reply to TommiT | On Saturday, 6 July 2013 at 16:40:25 UTC, TommiT wrote:
> ...does (barring it makes a temporary struct which holds one field for each of those converted const char pointers, ...
Should be "...one field per each of those..."
|
Copyright © 1999-2021 by the D Language Foundation