Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 07, 2016 New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Hi all, I have ~15y of C++ and now I want to test D, because it seems really intersting and "cleaner" than C++. As an exercice I m trying to implement something equivalent to the C++ std::integral_constant<T,T value> in D. In D: struct IntegralConstant(T, T VALUE) { ... } But I do not know how to write a compile-time type check. I tried template isIntegralConstant(ANY) { enum bool isIntegralConstant=__traits(identifier,ANY)=="IntegralConstant"; } But when using it with ANY=long type, I get a compile-time error: "argument long has no identifier" A workaround that worked is: struct IntegralConstantTag {} struct IntegralConstant(T, T VALUE) { private IntegralConstantTag selfTag_; alias selfTag_ this; } template isIntegralConstant(ANY) { enum bool isIntegralConstant=is(ANY : IntegralConstantTag); } But now I'm sticked by a compiler issue when I want to introduce 2 "alias this" to allow implicit conversion: struct IntegralConstant(T, T VALUE) { private IntegralConstantTag selfTag_; alias selfTag_ this; T value_=VALUE; alias value_ this; } Compiler error message is "integralConstant.d:16:3: error: there can be only one alias this". I would be very graceful for any help/advice that explains the right way to implement C++ std::integral_constant<T,T value> in the D language. Vincent |
November 07, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Picaud Vincent | On Monday, 7 November 2016 at 18:42:37 UTC, Picaud Vincent wrote: > template isIntegralConstant(ANY) > { > enum bool isIntegralConstant=__traits(identifier,ANY)=="IntegralConstant"; > } A bit more elegant way of doing that would be: enum isIntegralConstant(T) = is(T : IntegralConstant!U, U...); > I would be very graceful for any help/advice that explains the right way to implement C++ std::integral_constant<T,T value> in the D language. > > Vincent Now the question is, do you really need IntegralConstant? I've never used it in C++ so I don't really know any of the use cases for it. But generally in D if you need something to be a compile time constant value you can just use "enum". It can be any type as well, so long as it can be evaluated at compile time. enum long someConstant = 1 << 32; |
November 07, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jerry | On Monday, 7 November 2016 at 18:59:24 UTC, Jerry wrote: > On Monday, 7 November 2016 at 18:42:37 UTC, Picaud Vincent wrote: >> template isIntegralConstant(ANY) >> { >> enum bool isIntegralConstant=__traits(identifier,ANY)=="IntegralConstant"; >> } > > A bit more elegant way of doing that would be: > > enum isIntegralConstant(T) = is(T : IntegralConstant!U, U...); > > >> I would be very graceful for any help/advice that explains the right way to implement C++ std::integral_constant<T,T value> in the D language. >> >> Vincent > > Now the question is, do you really need IntegralConstant? I've never used it in C++ so I don't really know any of the use cases for it. But generally in D if you need something to be a compile time constant value you can just use "enum". It can be any type as well, so long as it can be evaluated at compile time. > > enum long someConstant = 1 << 32; Hi Jerry, Thank you so much for your quick answer! I tried your suggestion and it works. My main interest is numerical computations. I have some C++ libs using meta-programming and I want to see how I can translate some parts in D. The goal is to check: productivity & code readability & performance. I will try to implement 2 toy examples: 1/ A basic example of strided dense vector structure dealing with the dynamic/static size in an uniform way. In D I thing this can be done with something like this (not tried yet to compile it, but that is the idea to mimick my C++ implementation) struct Vector(T,SIZE,STRIDE) if( (is(SIZE==size_t)||isIntegralConstant!SIZE) ...) { alias T ElementType; private SIZE size_; private STRIDE stride_; ... auto required_capacity() { return size_*stride_; } // return a size_t or a IntegralConst static if ( isIntegralConstant!(typeof(required_capacity()) ) { } else { } } |
November 07, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Picaud Vincent | On Monday, 7 November 2016 at 21:23:37 UTC, Picaud Vincent wrote: > On Monday, 7 November 2016 at 18:59:24 UTC, Jerry wrote: >> On Monday, 7 November 2016 at 18:42:37 UTC, Picaud Vincent wrote: >>> template isIntegralConstant(ANY) >>> { >>> enum bool isIntegralConstant=__traits(identifier,ANY)=="IntegralConstant"; >>> } >> >> A bit more elegant way of doing that would be: >> >> enum isIntegralConstant(T) = is(T : IntegralConstant!U, U...); >> >> >>> I would be very graceful for any help/advice that explains the right way to implement C++ std::integral_constant<T,T value> in the D language. >>> >>> Vincent >> >> Now the question is, do you really need IntegralConstant? I've never used it in C++ so I don't really know any of the use cases for it. But generally in D if you need something to be a compile time constant value you can just use "enum". It can be any type as well, so long as it can be evaluated at compile time. >> >> enum long someConstant = 1 << 32; > > Hi Jerry, > > Thank you so much for your quick answer! I tried your suggestion and it works. > > My main interest is numerical computations. I have some C++ libs using meta-programming and I want to see how I can translate some parts in D. The goal is to check: productivity & code readability & performance. I will try to implement 2 toy examples: > > 1/ A basic example of strided dense vector structure dealing with the dynamic/static size in an uniform way. In D I thing this can be done with something like this (not tried yet to compile it, but that is the idea to mimick my C++ implementation) > > struct Vector(T,SIZE,STRIDE) if( (is(SIZE==size_t)||isIntegralConstant!SIZE) ...) > { > alias T ElementType; > > private SIZE size_; > private STRIDE stride_; > > ... > > auto required_capacity() { return size_*stride_; } // return a size_t or a IntegralConst > > static if ( isIntegralConstant!(typeof(required_capacity()) ) > { > } > else > { > } > > } Premature post send by error sorry.... Well something like: static if ( isIntegralConstant!(typeof(required_capacity()) ) ElementType[required_capacity()] data_; else ElementType[] data_; } For that, at least in C++, I need integral_constant<> type with compile-time arithmetic and smooth integration with "usual" size_t/ptrdiff_t types. 2/ I also would like to test some implementations concerning automatic differentiation. I have my own C++ libs, inspired, but ~20% faster than Adept: http://www.met.reading.ac.uk/clouds/adept/ and I would like to know how I can do that in D Well... That is the idea... I hope I will get some results and I will be happy to share if it is something interesting. Vincent |
November 07, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Picaud Vincent | On Monday, 7 November 2016 at 21:37:50 UTC, Picaud Vincent wrote:
>> static if ( isIntegralConstant!(typeof(required_capacity()) )
>> {
>> }
>> else
>> {
>> }
>>
>> }
>
> Premature post send by error sorry.... Well something like:
>
> static if ( isIntegralConstant!(typeof(required_capacity()) )
> ElementType[required_capacity()] data_;
> else
> ElementType[] data_;
> }
>
> For that, at least in C++, I need integral_constant<> type with compile-time arithmetic and smooth integration with "usual" size_t/ptrdiff_t types.
>
> 2/ I also would like to test some implementations concerning automatic differentiation.
> I have my own C++ libs, inspired, but ~20% faster than Adept:
> http://www.met.reading.ac.uk/clouds/adept/
> and I would like to know how I can do that in D
>
> Well... That is the idea... I hope I will get some results and I will be happy to share if it is something interesting.
>
> Vincent
Ah I get what you mean, you can do that without using a special type.
struct Vector(T, Args...) if(Args.length == 1)
{
static if(is(Args[0] == size_t))
{
size_t size;
}
else static if(Args[0] != 0) // would error if it's a type that's not size_t
{
enum size = Args[0];
}
else
{
static assert(0);
}
}
Vector!(int, 10) a;
Vector!(int, size_t) b; // both work with IntegralConstant
could use __traits(compiles) to see if it's not a type, for that second static if. Which would probably be better, so if you pass a float or something, it won't give a weird error.
|
November 07, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jerry | On Monday, 7 November 2016 at 22:18:56 UTC, Jerry wrote:
> On Monday, 7 November 2016 at 21:37:50 UTC, Picaud Vincent wrote:
>>> static if ( isIntegralConstant!(typeof(required_capacity()) )
>>> {
>>> }
>>> else
>>> {
>>> }
>>>
>>> }
>>
>> Premature post send by error sorry.... Well something like:
>>
>> static if ( isIntegralConstant!(typeof(required_capacity()) )
>> ElementType[required_capacity()] data_;
>> else
>> ElementType[] data_;
>> }
>>
>> For that, at least in C++, I need integral_constant<> type with compile-time arithmetic and smooth integration with "usual" size_t/ptrdiff_t types.
>>
>> 2/ I also would like to test some implementations concerning automatic differentiation.
>> I have my own C++ libs, inspired, but ~20% faster than Adept:
>> http://www.met.reading.ac.uk/clouds/adept/
>> and I would like to know how I can do that in D
>>
>> Well... That is the idea... I hope I will get some results and I will be happy to share if it is something interesting.
>>
>> Vincent
>
> Ah I get what you mean, you can do that without using a special type.
>
> struct Vector(T, Args...) if(Args.length == 1)
> {
> static if(is(Args[0] == size_t))
> {
> size_t size;
> }
> else static if(Args[0] != 0) // would error if it's a type that's not size_t
> {
> enum size = Args[0];
> }
> else
> {
> static assert(0);
> }
> }
>
> Vector!(int, 10) a;
> Vector!(int, size_t) b; // both work with IntegralConstant
>
> could use __traits(compiles) to see if it's not a type, for that second static if. Which would probably be better, so if you pass a float or something, it won't give a weird error.
Thank you again Jerry!
For sure my way of thinking is twisted by my C++ habits! :-/
The positive point is that D seems to offer much shorter solutions (this is my hope).
However I still need some investigations and/or some guidance:
-> not sure that it is ok for me as I really want to track "static constants" all the
way long.
That is the reason why I introduced the IntegralConstant type
(with operator overloading, work in progress)
For instance, the code:
enum int a=1,b=2;
auto c = a+b;
pragma(msg,typeof(c)); // prints "int"
static assert(c==3); // compilation fails: "variable c cannot be read at compile time"
To implement my vector structs I need:
1/ a way to detect compile-time constant vs "dynamic" values
2/ to perform and to propagate compile-time constants across "arithmetic" computations.
For instance to compute the required capacity to store vector data, I need something
like
auto capacity = max(0,(size_-1)*stride_);
and this expression must make sense for both "dynamic" values and compile-time constant.
In one case I expect
typeof(capacity) -> int,
in the other
typeof(capacity) -> IntegralConst
|
November 07, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Picaud Vincent | typo... auto capacity = max(0,(size_-1)*stride_+1); |
November 07, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Picaud Vincent | On Monday, 7 November 2016 at 23:07:27 UTC, Picaud Vincent wrote: > typo... > auto capacity = max(0,(size_-1)*stride_+1); To be more correct I have something like: alias IntergralConstant!(int,0) Zero_c; alias IntergralConstant!(int,1) One_c; auto capacity = max(Zero_c,(size_-One_c)*stride_+One_c); with "smooth" implicit conversion IntegralConstant -> int for cases where size_ or stride_ are "int" and not both IntegralConstant types. |
November 08, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Picaud Vincent | On Monday, 7 November 2016 at 23:03:32 UTC, Picaud Vincent wrote: > I need: > > 1/ a way to detect compile-time constant vs "dynamic" values /** * Indicates if something is a value known at compile time. * * Params: * V = The value to test. * T = Optional, the expected value type. */ template isCompileTimeValue(alias V, T...) if (T.length == 0 || (T.length == 1 && is(T[0]))) { enum isKnown = is(typeof((){enum v = V;})); static if (!T.length) enum isCompileTimeValue = isKnown; else enum isCompileTimeValue = isKnown && is(typeof(V) == T[0]); } /// unittest { string a; enum b = "0"; enum c = 0; static assert(!isCompileTimeValue!a); static assert(isCompileTimeValue!b); static assert(isCompileTimeValue!c); static assert(isCompileTimeValue!(b,string)); static assert(isCompileTimeValue!(c,int)); static assert(!isCompileTimeValue!(c,char)); static assert(!isCompileTimeValue!(char)); } |
November 08, 2016 Re: New to D and mimicking C++ : how to implement std::integral_constant<>? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | Hi Basile, Thank you for your code, it allowed me to grasp a little bit more about how to do things in D. Vincent |
Copyright © 1999-2021 by the D Language Foundation