inout type constructor applied to this-reference

2014-01-10 Thread Matthias Walter
Hi,

I read about inout functions in the language documentation which allows
to use inout in order to set the constness of the return type based on
the constness of some argument. What is not mentioned is that this also
works for the this-reference by marking the function itself inout:

So instead of

class C
{
  OtherClass foo;

  const(OtherClass) getOther() const { return foo; }
  OtherClass getOther() { return foo; }
}

we can write

class C
{
  OtherClass foo;

  inout(OtherClass) getOther() inout { return foo; }
}

Since the documentation only talks about marking arguments inout, can I
nevertheless rely on its behavior? Anyways, I think it is worth to be
included in the docs.

Best regards,

Matthias


Re: Getting a range over a const Container

2012-07-19 Thread Matthias Walter
On 07/19/2012 06:44 AM, Jonathan M Davis wrote:
 On Thursday, July 19, 2012 04:39:26 Francisco Soulignac wrote:
 So, my question is how can I (correctly) traverse a const SList,
 const DList, etc?
 
 Right now? I'm pretty sure that that's impossible. Hopefully that will 
 change, 
 but getting const and ranges to work together can be rather difficult, and 
 std.container needs more work in that regard.

Well it doesn't work yet. But in principle it could since we can always
copy a const pointer to a non-const one to const data:

Node* actual; // but 'this' is const and hence the type is const(Node*)

const(Node)* i_will_traverse = actual;

Best regards,

Matthias


Re: ~= call copy ctor?

2012-07-19 Thread Matthias Walter
On 07/19/2012 02:27 PM, Namespace wrote:
 I have a 2 questions.
 
 I have this code:
 
 [code]
 import std.stdio;
 
 struct Test {
 public:
 this(int i = 0) {
 writeln(Test CTor.);
 }
 
 this(this) {
 writeln(Test Copy CTor);
 }
 
 ~this() {
 writeln(Test DTor);
 }
 }
 
 Test[] _arr;
 
 void copy_save(Test t) {
 _arr ~= t;
 }
 
 void by_ref_save(ref Test t) {
 _arr ~= t;
 }
 
 [/code]
 
 Why get i with
 
 [code]
 void main() {
 Test t = 42;
 
 by_ref_save(t);
 }
 [/code]
 
 this output:
 
 Test CTor.
 Test Copy CTor
 Test DTor

As you mentioned in the subject the copy constructor is not called while
the struct is passed by reference but on array concatenation.
But this must occur since the array has its memory region and the
original variable t in main() also has. Since they are different, at
some point the struct must be copied from t in main() into the array.
The ref only ensures that it is passed via reference (a pointer to the
memory of t in main()) to the function by_ref_save().

 And the same if i have this:
 
 [code]
 void main() {
 Test t = 42;
 
 copy_save(t);
 }
 [/code]
 
 t is already a clone. Why it is copied again?

Here it is once copied from t in main() into the local variable t in
copy_save() and then copied (as in your 1st example) into the array.
Imagine the copy_save routine is in a different module and only its
signature is exposed to main. When calling the function, the compiler
does not know what happens inside copy_save but it must put the variable
onto the stack at the position of the first parameter (well, in this
case it is probably put into a CPU register, but that doesn't matter here).

Then, when copy_save is invoked it only knows the local variable which
it then copies into the array memory (after enlarging the array).

It *may* be the when you enable compiler optimizations (-O -inline) that
copy_save gets inlined and hence the compiler can optimize one of the
copy calls away. But that I don't know for sure.

Best regards,

Matthias


Re: ~= call copy ctor?

2012-07-19 Thread Matthias Walter
On 07/19/2012 03:00 PM, Namespace wrote:
 Is there any way to avoid the implizit copy ctor by array concatenation?
 Or is the only way to use a pointer?

Yes, in some way you have to. If you want to not copy a lot of data (or
avoid additional on-copy effort) you either have to you pointers
explicitly (Test*[]) or implicitly. The latter works e.g. by making Test
a class which means that the variable actually does store a pointer to
the instance.

Note that for struct pointers you should not escape them, i.e. have a
variable local in a function, puts its address into some array and
returning that array. Since the local variable is gone, the pointer is
invalid as well. (Nothing happens if you do not access it).

Best regards,

Matthias


Re: foreach syntax

2012-06-29 Thread Matthias Walter
On 06/29/2012 12:47 PM, Namespace wrote:
 A friend of mine ask me why D's foreach isn't like C#
 
 Means, why is it like
 int[] arr = [1, 2, 3];
 
 foreach (int val; arr) {
 
 and not
 foreach (int val in arr) {
 
 which it is more intuitive.
 
 I could give him no clever answer to, so maybe someone here knows the
 reasons.
 

I suppose it is because the usual 'for' loop is a relative of 'foreach'.
And there we (and the C world) uses ';'.


Getting a range over a const Container

2012-06-15 Thread Matthias Walter
Hi,

I have a const std.container object (e.g., a const(Array!int)) of which
I'd like to have a range which can traverse that container having
read-only access. This does not seem to be possible with opSlice(). Is
there an alternative?

Best regards,

Matthias


Re: const version for foreach/opApply

2012-06-11 Thread Matthias Walter
On 06/10/2012 12:30 AM, Era Scarecrow wrote:
 On Saturday, 9 June 2012 at 10:09:25 UTC, Matthias Walter wrote:
 First, thank you for your answer. I've already made some tiny
 modifications in order to make BitArray work for my purposes:

 https://github.com/xammy/phobos/commit/eb46d99217f2bf1e6d173964e2954248b08146d6


 If you plan to create pull requests for your changes - please consider
 my changes as well. When do you expect to finish, I.e., create a pull
 request for phobos?
 
  Curious... Almost all of the changes you proposed I've already added in
 my version, the toHash is the only one missing and I don't know if I can
 work that very well. The new version is going to include 'slice-like'
 features, which is mostly a couple extra numbers specifying the offset
 in bits from the beginning to the end; The problem with that is hashing
 would have a huge speed drop.
 
  I'm adding an 'realign' function that handles those cases, but the
 downside is shared slices where you would want to make changes may or
 may not work. Caching the result would also be useful... Hmmm...
 
  I don't suppose you have a toHash where I can enter the odd bits and
 then also bulk ones and have the hash return the same could you? I can

I see the problem. I don't know whether my hash function is a good one -
I just needed it to make AAs work with BitArray as a key type.

But the question is interesting. Finding a good hash function for bit
arrays which is invariant under realignment.

 see xor easily having this type of effect...
 
  Anyways, here's some things I can do so far; Got a few improvements
 left to do, but not many. (const  immutable friendly of course :) )
 
 -- 
 
 const BitArray ba = BitArray([1,1,0,0,1]);
 const BitArray slice = ba[1 .. ba.length];
 BitArray m = slice.dup;
 immutable BitArray im = slice.idup;
 
 assert(slice == ba[1 .. ba.length]);
 assert(slice == [1,0,0,1]);
 assert(slice == m);
 assert(slice == im);
 
 assert(slice.isCompact);
 writeln(GC not used);
 

Looks interesting!




Re: const version for foreach/opApply

2012-06-09 Thread Matthias Walter
On 2012-06-08 22:47, Era Scarecrow wrote:
 On Friday, 8 June 2012 at 16:33:28 UTC, Matthias Walter wrote:
 Hi,

 trying to traverse the entries of a std.bitmanip.BitArray I stumbled
 upon the following problem:

 In case I want to accept const(BitArray) objects, it shall look like
 the following (maybe using ref const(bool) for the delegate
 parameter?):

 int opApply(scope int delegate(bool) dg) const
 

 Can one glue both things together into a single routine (using inout
 magic or whatever)?
 
  I want to say you can't, because ref bool. If you ignore the reference,
 you don't need the non-const version (I think).
 
  I am currently working on BitArray updates, and it is const/immutable
 friendly according to as many tests as I could come up with for valid
 usage; This has taught me a lot on using templates, traits, constraints
 and how inout actually works. I haven't tried for a bit but I can try
 once more to send my code to GitHub, then you can give it a try.

First, thank you for your answer. I've already made some tiny
modifications in order to make BitArray work for my purposes:

https://github.com/xammy/phobos/commit/eb46d99217f2bf1e6d173964e2954248b08146d6

If you plan to create pull requests for your changes - please consider
my changes as well. When do you expect to finish, i.e., create a pull
request for phobos?


const version for foreach/opApply

2012-06-08 Thread Matthias Walter
Hi,

trying to traverse the entries of a std.bitmanip.BitArray I stumbled
upon the following problem:

The original code is as follows:

int opApply(scope int delegate(ref bool) dg)
{
  int result;
  for (size_t i = 0; i  len; i++)
  {
bool b = opIndex(i);
result = dg(b);
this[i] = b;
if (result)
  break;
  }
  return result;
}

In case I want to accept const(BitArray) objects, it shall look like the
following (maybe using ref const(bool) for the delegate parameter?):

int opApply(scope int delegate(bool) dg) const
{
  int result;
  for (size_t i = 0; i  len; i++)
  {
bool b = opIndex(i);
result = dg(b);
if (result)
  break;
  }
  return result;
}

Can one glue both things together into a single routine (using inout
magic or whatever)?

Best regards,

Matthias Walter


Re: How to test for equality of types?

2012-05-19 Thread Matthias Walter
On 2012-05-19 09:05, Philippe Sigaud wrote:
 On Fri, May 18, 2012 at 11:51 PM, Simen Kjaeraas simen.kja...@gmail.com 
 wrote:
 
 Because Wrapper!(AliasStruct).Wrap does not exist. And _error_ is not
 equal to any other type.
 
 Yes. Wrap is included in the complete template name (Wrapper!(Wrap))
 and has no independent existence.
 You _can_ get access to it by exposing it as an alias, as you do in 
 AliasStruct:
 
 struct Wrapper(Wrap)
 {
 alias Wrap Wrapped; // cannot call it 'Wrap'
  ...
 
 }

Yes, of course you are right. This was my fault - after exposing it via
an alias, it prints true.

 (third case)
 false


 And here I disagree. This prints true on 2.059. Regression?
 
 AFAICT, this should print true.
 
 And, concerning Artur questio, on 2.059 (Linux):
 
  pragma(msg, is(w._wrap.Alias == AliasStruct.Alias));//   - true
  pragma(msg, typeof(w._wrap).Alias.stringof); // - MyStruct
  pragma(msg, AliasStruct.Alias.stringof); // - MyStruct

I would open a bug report with the following code which is a bit smaller
than my first wrong version:

=
module main;

struct MyStruct { }

struct AliasStruct
{
  alias MyStruct Alias;
}

struct Wrapper
{
  AliasStruct aliasStruct;
}

void main()
{
  Wrapper w;

  pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct
  pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
  static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true
  static assert(is(typeof(w.aliasStruct).Alias == AliasStruct.Alias));
// - false
}
=

Best regards,

Matthias


Re: How to test for equality of types?

2012-05-19 Thread Matthias Walter
On 2012-05-19 15:28, Philippe Sigaud wrote:
 On Sat, May 19, 2012 at 12:23 PM, Matthias Walter
 xa...@xammy.homelinux.net wrote:
 
 I would open a bug report with the following code which is a bit smaller
 than my first wrong version:

 =
 (...)
  pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct
  pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
  static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true
  static assert(is(typeof(w.aliasStruct).Alias == AliasStruct.Alias));
 // - false
 }
 
 Seems like a pb concerning whether Alias is a type or a symbol. See
 A,B,C,D below:
 
 void main()
 {
  Wrapper w;
 
  pragma(msg, typeof(w.aliasStruct).Alias.stringof); // - MyStruct
  pragma(msg, AliasStruct.Alias.stringof); // - MyStruct
  static assert(is(typeof(w.aliasStruct) == AliasStruct)); // - true
  static assert(is(w.aliasStruct.Alias == AliasStruct.Alias)); // - true
 
  alias typeof(w.aliasStruct) A; // - OK
  //alias typeof(w.aliasStruct).Alias B; // - NOK
  //alias A.Alias C; // - NOK
  alias w.aliasStruct.Alias D; // - OK
 
  static assert(is(A.Alias == AliasStruct.Alias)); // - true
  //static assert(is(B == AliasStruct.Alias));
  //static assert(is(C == AliasStruct.Alias));
  static assert(is(D == AliasStruct.Alias)); // - true
 }
 
 I think A is enough for your need, but I don't get why B and C are not
 accepted (DMD 2.059, Linux)
 

Using the current git version of dmd I realized that C works! Hence, as
a workaround it can be used by creating a local alias A and subsequently
using A.Alias in the is-expressions. But it seems odd that

alias typeof(X).A B; does not work but
alias typeof(X) Y; alias Y.A B; does.

Is this considered as a bug?

Best regards,

Matthias


How to test for equality of types?

2012-05-18 Thread Matthias Walter
Hi,

how do I test two types for equality? Suppose I have A and B aliasing
some type(s), how do I find out if they are aliases the same thing?

I tried the is(A == B) expression, but this does not always work (tell
me if I shall give an example).

On the other hand, according to the spec the IsExpression is not
supposed to compare two aliases with each other.

Best regards,

Matthias


Re: How to test for equality of types?

2012-05-18 Thread Matthias Walter


On 2012-05-18 16:12, Steven Schveighoffer wrote:
 On Fri, 18 May 2012 06:06:45 -0400, Matthias Walter wrote:
 how do I test two types for equality? Suppose I have A and B aliasing
 some type(s), how do I find out if they are aliases the same thing?

 I tried the is(A == B) expression, but this does not always work (tell
 me if I shall give an example).
 
 I would expect this to work.  What situation does it not (maybe you
 aren't actually testing for equality there).
 
 It could be a bug...

=

struct MyStruct { }

struct Wrapper(Wrap)
{
  Wrap _wrap;

  this(Wrap wrap)
  {
_wrap = wrap;
  }
}


struct AliasStruct
{
public:
  alias MyStruct Alias;
}


int main(char[][] args)
{
  auto w = Wrapper!(AliasStruct)(AliasStruct.init);
  pragma(msg, is(Wrapper!(AliasStruct).Wrap == AliasStruct) ? true :
false);
  pragma(msg, is(typeof(w._wrap) == AliasStruct) ? true : false);
  pragma(msg, is(typeof(w._wrap).Alias == AliasStruct.Alias) ? true :
false);


  return 0;
}
=

prints out

false
true
false

during compilation using current git version of dmd. In my application I
used the third case, i.e., wanted to find out whether they alias the
same thing.

 On the other hand, according to the spec the IsExpression is not
 supposed to compare two aliases with each other.
 
 where does it say that?

Okay, this seems to be my fault. It states different cases for the RHS
operator of is(LHS == RHS), e.g., Type == TypeSpecialization, but
nothing like Type == Type. But TypeSpecialization includes Type as well...

Best regards,

Matthias


Remarks on std.container

2012-03-08 Thread Matthias Walter
Hi,

I wanted to have a binary heap where I can update entries and restore
the heap structure.

1. First I observed that due to the implementation of
std.container.BinaryHeap, keeping track of the position of a certain
value in the heap cannot be done directly, but it would be helpful to
pass a Swapper object (or function) to the methods that may change the
order of the elements such that this Swapper is called for every swap()
operation such that the user of the BinaryHeap can keep track of the
permutation.

2. I tried to create a heap structure on my own, using
std.container.Array as a store. Of course, it I also needs to perform
swap operations, but the following did not work:

std.algorithm.swap(arrayInstance[i], arrayInstance[j]);

Also there is no usable swap() method of Array. So do I really have to
perform the swap on my own? I mean, 3 lines of code aren't that much but
I really expected an easy way.

3. For my structure I wanted to check the heap structure in an
invariant(). Unfortunately, accessing stored elements of Array is no
const operation, hence I could not implement such an invariant.

Maybe I'm not using it correctly, so any help or comments would be nice.

Best regards,

Matthias


Mixture of type tuple and expression tuple

2012-02-06 Thread Matthias Walter
Hi,

I'd like to have a function foo which shall depend on several
compile-time expressions (e.g. strings) and gets several arguments whose
types are templatized. Here, several means in both cases that the
number of expressions/arguments are to be determined at compile-time.
Here is an example:

foo!(a, b, c)(42, new MyClass(), 7.0);

At compile-time, some template parameters (strings a, b and c)
shall be given explicitly and some more template parameters (types of
arguments int, MyClass, double) shall be deduced from the function
arguments.

Is that possible? Of course, I cannot setup two TemplateTupleParameters.

Best regards,

Matthias



dup method const or not?

2011-11-27 Thread Matthias Walter
Hi,

Recently, I realized that several dup methods in D2's phobos are
declared like the one for BitArray:

@property BitArray dup()

My question is why it is declared without const? Is it a bug or is
there a reason for it? I can think of a case where one only has
implemented a shallow copy and wants to omit the const due to the
involved transitivity, but this shouldn't be the case for BitArray (the
underlying array is dup'ed). Is there a general rule/recommendation when
to make a dup method const and when not? My problem arises in a copy
constructor for a struct S which takes a const(S) instance. But as S has
a BitArray member, duping is not allowed, so I need a way to duplicate a
const(BitArray) object.

Matthias


Re: dup method const or not?

2011-11-27 Thread Matthias Walter
On 2011-11-27 23:48, mta`chrono wrote:
 that's a real good question. it fails with the following error:
 
 Error: function std.bitmanip.BitArray.dup () is not callable using
 argument types () const
 
 
 here is a hack:
 
 ---
 import std.bitmanip;
 import core.stdc.string;
 
 void main()
 {
 const(BitArray) foo;
 BitArray bar;
 
 memcpy(bar, foo, BitArray.sizeof);
 }

Well, this hack doesn't even work - as it does a shallow copy only,
immediately setting bits of bar also changes bits of foo!

Matthias


BinaryHeap usage

2010-12-14 Thread Matthias Walter
Hi all,

suppose I have an array of comparable Foo structs which I want to access
in a sorted order (e.g. a priority queue) using a BinaryHeap object (I
know that for just sorting, the BinHeap is not the right tools), but I
do not want to change the order of the objects in the original array.

I have two ideas on how to do this and just want to know whether they
are the right way:

a) Have an array of Foo*, initialize it from the original and
instantiate the BinaryHeap with a Comparision-predicate that
dereferences first.

b) Have an array of indices that are indicies in the original array
(like a permutation in a permutation group) and access the corresponding
index of the original array for comparison.

Any further ideas for this problem, or did I cover everything already?

Matthias


Re: D2 byChunk

2010-12-11 Thread Matthias Walter


On 12/11/2010 01:00 AM, Christopher Nicholson-Sauls wrote:
 On 12/10/10 22:36, Matthias Walter wrote:
 On 12/10/2010 09:57 PM, Matthias Walter wrote:
 Hi all,

 I currently work on a parser for some file format. I wanted to use the
 std.stdio.ByChunk Range to read from a file and extract tokens from the
 chunks. Obviously it can happen that the current chunk ends before a
 token can be extracted, in which case I can ask for the next chunk from
 the Range. In order to keep the already-read part in mind, I need to dup
 at least the unprocessed part of the older chunk and concatenate it in
 front of the next part or at least write the code that works like they
 were concatenated. This looks like a stupid approach to me.

 Here is a small example:

 file contents: Hello world
 chunks: Hello w orld

 First I read the token Hello from the first chunk and maybe skip the
 whitespace. Then I have the w (which I need to move away from the
 buffer, because ByChunk fill overwrite it) and get orld.

 My idea was to have a ByChunk-related Object, which the user can tell
 how much of the buffer he/she actually used, such that it can move this
 data to the beginning of the buffer and append the next chunk. This
 wouldn't need further allocations and give the user contiguous data
 he/she can work with.
 I coded something that works like this:

 foreach (ref ubyte[] data; byBuffer(file, 12))
 {
   writefln([%s], cast(string) data);
   data = data[$-2 .. $];
 }

 The 2nd line in the loop tells ByBuffer that we didn't process the last
 two chars and would like to get them again along with newly read data.
 And as long as we do process something, the internal buffer does not get
 reallocated.

 It works and respects the formal requirements of ranges. Whether it
 respects the intended semantics, one can discuss about. Any comments
 whether the above things make sense or is an evil exploit of the
 provided syntax sugar?
 I don't think it's a bad approach, but I have a suggestion.

 It leaves a lot of room for abuse or misuse if you require the user code
 to modify the data[] array in order to send this protect some
 characters message.  I think it would be better to provide an explicit
 function/method that means precisely that.  Maybe return a transparent
 struct wrapping a view to the buffer's data, that further provides a
 function for doing precisely this.

 foreach( data; byBuffer( file, 12 )) {
   // do things with data, decide we need to keep 2 chars
   data.save( 2 );
 }

 Or something like it.  With regards to this, you may want to allow the
 internal buffer to grow (if you aren't already) as needed.  Imagine what
 would otherwise happen if you needed to 'save' the entire current buffer.

 -- Chris N-S
Thank you! This is a really good idea. So I basically wrap the
buffer-array and implement it such that the default behavior (without
explicitely doing something) is like the ByChunk mechanism.

Matthias


Re: setting array dimensions at runtime

2010-12-05 Thread Matthias Walter

 The only thing I've been able to think of is

byte[][] a;
a.length = size;
for (int i; i  size; i++) {
 a[i].length = size;
}
Well, you can do at least:

auto a = new byte[][size];
foreach (ref row; a)
  row = new byte[size];

Matthias



Re: bigint

2010-11-28 Thread Matthias Walter
On 11/27/2010 02:05 PM, bearophile wrote:
 Reduced case for bugzilla:
 
 http://d.puremagic.com/issues/show_bug.cgi?id=5281
   
I investigated into the bug and the reason is the signature of opEquals,
which currently is

bool opEquals(Tdummy=void)(ref const BigInt y) const
bool opEquals(T: int)(T y) const

The only working sigature for array-of-structs-comparison to work is

bool opEquals(ref const BigInt y) const

But this removes the ability to compare against ints.
(btw, it should probably be long in the 2nd signature?!)

array-comparison should definitely take templated opEquals functions
into account, or is there something mentioned in the spec?

Matthias


Current status of toString in phobos

2010-11-17 Thread Matthias Walter
Hi,

I'm currently using DMD v2.049 with phobos. I found an old discussion
about how toString should be designed and how it is supposed to work. As
the following code does not print out the number, I wonder what is the
current status of how to implement a toString function for a struct/class:

| auto n = BigInt(42);
| writefln(%s, n);

Thanks
Matthias


Re: A module comprehensive template-specialization

2010-06-28 Thread Matthias Walter
On 06/28/2010 05:32 AM, Simen kjaeraas wrote:
 Matthias Walter xa...@xammy.homelinux.net wrote:
 
 Can I handle this in another way (like making the template a conditional
 one)?
 
 Template constraints[1] sounds like what you want.
 
 Basically, you want the following:
 
 == Module a ==
 | module a;
 |
 | template Base (T) if (!is(T t : t*))
 | {
 |   alias T Base;
 | }
 
 == Module b ==
 | module b;
 |
 | import a;
 |
 | template Base(T) if (is(T t : t*))
 | {
 |   alias Base !(T) Base;
 | }
 
 == Main module ==
 |
 |  import a, b;
 |
 | int main(char[][] args)
 | {
 |   alias Base !(int*) foo;
 |
 |   return 0;
 | }
 
 Not tested, ymmv.
 
 [1]: http://digitalmars.com/d/2.0/template.html#Constraint
 

The problem with constraints arises when I want to make an existing
class (who's code I cannot modify) match a Concept, in which case I
would just add another template specialization for this class. Here I
would have to add further conditions to the template constraints, which
would also mean to modify a library. A prominent example for Boost Graph
Library is the LEDA graph class, which can be enabled to be used by BGL
by more or less just specializing the graph_traits template.

Any further ideas?


Re: A module comprehensive template-specialization

2010-06-28 Thread Matthias Walter
On 06/28/2010 09:49 AM, Justin Spahr-Summers wrote:
 On Sun, 27 Jun 2010 18:51:35 +0200, Matthias Walter 
 xa...@xammy.homelinux.net wrote:

 Hi list,

 I tried to write a traits class comparable to iterator_traits in C++ STL
 or graph_traits in Boost Graph Library in D 2.0, but failed to do so via
 template specialization which is put into different modules. Putting
 everything into one module interferes with extensibility. I tried the
 following:

 == Module a ==
 | module a;
 |
 | template Base (T)
 | {
 |   alias T Base;
 | }

 == Module b ==
 | module b;
 |
 | import a;
 |
 | template Base(T: T*)
 | {
 |   alias Base !(T) Base;
 | }

 == Main module ==
 |
 |  import a, b;
 |
 | int main(char[][] args)
 | {
 |   alias Base !(int*) foo;
 |
 |   return 0;
 | }

 The error message is:
 bug.d(8): Error: template instance ambiguous template declaration
 b.Base(T : T*) and a.Base(T)

 Can I handle this in another way (like making the template a conditional
 one)?

 best regards
 Matthias Walter
 
 I believe this is intended behavior, as it prevents template hijacking 
 and the like. Using alias to import the two templates into the same 
 scope might help, though I'm not sure exactly how it should be done.

I tried to do so in some variants but did not succeed unfortunately. If
you have a precise idea, please let me know!

 
 On another note, though, have you looked at __traits() and std.traits?

I looked at them but didn't find them helpful for this precise problem.
The whole reason for doing this is to make it possible to make another
existing class model the concept (i.e. have some aliases / typedefs
done) of my library class without editing any of them. As I mentioned in
my other response, a prominent example for Boost Graph
Library is the LEDA graph class, which can be enabled to be used by BGL
by more or less just specializing the graph_traits template. I'd like to
have this kind of technique available, too.

Any further suggestions?


A module comprehensive template-specialization

2010-06-27 Thread Matthias Walter
Hi list,

I tried to write a traits class comparable to iterator_traits in C++ STL
or graph_traits in Boost Graph Library in D 2.0, but failed to do so via
template specialization which is put into different modules. Putting
everything into one module interferes with extensibility. I tried the
following:

== Module a ==
| module a;
|
| template Base (T)
| {
|   alias T Base;
| }

== Module b ==
| module b;
|
| import a;
|
| template Base(T: T*)
| {
|   alias Base !(T) Base;
| }

== Main module ==
|
|  import a, b;
|
| int main(char[][] args)
| {
|   alias Base !(int*) foo;
|
|   return 0;
| }

The error message is:
bug.d(8): Error: template instance ambiguous template declaration
b.Base(T : T*) and a.Base(T)

Can I handle this in another way (like making the template a conditional
one)?

best regards
Matthias Walter