Comment #0 by john.loughran.colvin — 2014-03-25T05:45:13Z
Typedef really doesn't work.
import std.typecons;
alias Int = Typedef!(int);
unittest
{
Int a, b;
a += b;
}
typecons.d-mixin-3918(3918): Error: incompatible types for (this.Typedef_payload) += (v)): 'int' and 'Typedef!(int, 0)'
/d32/f264.d(8): Error: template instance std.typecons.Typedef!(int, 0).Typedef.Proxy!(Typedef_payload).opOpAssign!("+", Typedef!(int, 0), Typedef!(int, 0)) error instantiating
/d32/f264.d(8): Error: 'a += b' is not a scalar, it is a Typedef!(int, 0)
/d32/f264.d(8): Error: 'a' is not of arithmetic type, it is a Typedef!(int, 0)
/d32/f264.d(8): Error: 'b' is not of arithmetic type, it is a Typedef!(int, 0)
Comment #1 by andrej.mitrovich — 2014-04-23T20:14:41Z
This seems to be a Proxy issue. Kenji, if I add the following to Proxy:
-----
private enum getField(T) = is(T == typeof(this))
? ("." ~ __traits(identifier, a)) : "";
auto ref opOpAssign(string op, this X, V)(auto ref V v)
{
return mixin("a " ~ op ~ "= v" ~ getField!V);
}
-----
Then the OP code will work. But I'm not sure if this is the appropriate fix. Do you have a better idea?
Comment #2 by bearophile_hugs — 2014-04-23T21:21:11Z
(In reply to Andrej Mitrovic from comment #1)
> But I'm not sure if this is the appropriate fix.
> Do you have a better idea?
In Haskell this doesn't compile (newtype is a built-in that is similar to Typedef):
newtype T = T Int
main = do
let a = 10 :: T
let b = 20 :: T
let c = a + b :: T
print c
You have to ask the compiler to activate the arithmetic operations between two newtypes:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype T = T Int deriving (Num, Show)
main = do
let a = 10 :: T
let b = 20 :: T
let c = a + b :: T
print c
And now it prints:
T 30
Comment #3 by andrej.mitrovich — 2014-04-23T21:26:26Z
(In reply to bearophile_hugs from comment #2)
> (In reply to Andrej Mitrovic from comment #1)
>
> > But I'm not sure if this is the appropriate fix.
> > Do you have a better idea?
>
> In Haskell this doesn't compile (newtype is a built-in that is similar to
> Typedef).
> You have to ask the compiler to activate the arithmetic operations between
> two newtypes.
Sounds like a more configurable and complex version of Typedef. Note that 99% of the work of Typedef is done by Proxy, Typedef simply stores a Proxy inside and otherwise has a very minimal implementation.
Anyway I could imagine there is a million little ways you could configure a Typedef, but maybe it's best to have the scaffolding available as a set of mixin templates, so the user can easily create their own specific versions, e.g.:
struct UserTypedef(T)
{
mixin MixOverload!"opUnary"; // implement opUnary
mixin MixOverload!"opBinary"; // implement opBinary
}
This is probably simpler than having a super-complicated generic Typedef structure such as:
struct Typedef(bool useOpUnary, bool useOpBinary, ...);
Comment #4 by bearophile_hugs — 2014-04-23T21:49:23Z
(In reply to Andrej Mitrovic from comment #3)
> struct UserTypedef(T)
> {
> mixin MixOverload!"opUnary"; // implement opUnary
> mixin MixOverload!"opBinary"; // implement opBinary
> }
>
> This is probably simpler than having a super-complicated generic Typedef
> structure such as:
>
> struct Typedef(bool useOpUnary, bool useOpBinary, ...);
Note: I didn't open this enhancement request.
A simpler solution is to offer a way to get the underlying value:
a.get += b.get;
In Haskell you can define the Num typeclass operations of a newclass, or just define a simple function that uses pattern matching, and I use pattern matching again to print it:
newtype T = T Int
add :: T -> T -> T
T a `add` T b = T (a + b)
main = do
let a = T 10
let b = T 20
let c = a `add` b
let T d = c
print d
Comment #5 by dlang-bot — 2019-12-30T12:29:02Z
@berni44 created dlang/phobos pull request #7338 "Fix Issue 12461 - Typedef and opOpAssign" fixing this issue:
- Fix Issue 12461 - Typedef and opOpAssign
https://github.com/dlang/phobos/pull/7338
Comment #6 by dlang-bot — 2019-12-31T09:24:47Z
dlang/phobos pull request #7338 "Fix Issue 12461 - Typedef and opOpAssign" was merged into master:
- 998ac2bc36e2b0f0ef44837a937871d0d4a0a89c by Bernhard Seckinger:
Fix Issue 12461 - Typedef and opOpAssign
https://github.com/dlang/phobos/pull/7338