May 30, 2012
Hi,

I've the following enumeration:

enum path : string {

  log1 = "/var/log1",
  log2 = "/var/log2"

}

Now... when I try to do the following:

string subDirectory = "example";

string newPath = buildPath(path.log1, subDirectory);

I get the following errors:

Error: template std.path.buildPath does not match any function template
declaration
Error: template std.path.buildPath(C) if (isSomeChar!(C)) cannot deduce
template function from argument types !()(path,string)
Error: template std.path.buildPath does not match any function template
declaration
Error: template std.path.buildPath(C) if (isSomeChar!(C)) cannot deduce
template function from argument types !()(path,string)

Is this a bug in std.path.buildPath() or is there anything I'm doing wrong?
May 30, 2012
nrgyzer:

> Is this a bug in std.path.buildPath() or is there anything I'm doing wrong?

The signature of buildPath is:

immutable(C)[] buildPath(C)(const(C[])[] paths...);

But your inputs aren't of the same type. Named enum create their own type. You give buildPath a type string and a type path, that is not a string.

There are various solutions, this compiles, but it's not very safe:

buildPath(cast(string)path.log1, subDirectory);

Another solution is to not use a named enum:

enum : string {
    path_log1 = "/var/log1",
    path_log2 = "/var/log2"
}

buildPath(path_log1, subDirectory)

In bugzilla I have asked for an enum property that returns the raw value&type of an enum.

Bye,
bearophile
May 30, 2012
A better solution is to use:

struct Path {
    enum : string {
        log1 = "/var/log1",
        log2 = "/var/log2"
    }
}


Or even just:

struct Path {
    enum string log1 = "/var/log1",
                log2 = "/var/log2";
}

(In D structs, classes and enums start with an upper case).

Bye,
bearophile
May 30, 2012
== Auszug aus bearophile (bearophileHUGS@lycos.com)'s Artikel
> nrgyzer:
> > Is this a bug in std.path.buildPath() or is there anything I'm
> > doing wrong?
> The signature of buildPath is:
> immutable(C)[] buildPath(C)(const(C[])[] paths...);
> But your inputs aren't of the same type. Named enum create their
> own type. You give buildPath a type string and a type path, that
> is not a string.
> There are various solutions, this compiles, but it's not very
> safe:
> buildPath(cast(string)path.log1, subDirectory);
> Another solution is to not use a named enum:
> enum : string {
>      path_log1 = "/var/log1",
>      path_log2 = "/var/log2"
> }
> buildPath(path_log1, subDirectory)
> In bugzilla I have asked for an enum property that returns the
> raw value&type of an enum.
> Bye,
> bearophile

Alright, thanks... but I want to do the following:

foreach(c; __traits(allMembers, path))
 if (!exists(mixin("path." ~ c))) mkdirRecurse(mixin("path." ~ c));

When I use a named enum, I can't use the source above... so I've to cast in the buildPath()-method to my path enumeration or is there any other chance to realize the foreach-loop?
May 30, 2012
On 05/30/12 20:34, nrgyzer wrote:
> Hi,
> 
> I've the following enumeration:
> 
> enum path : string {
> 
>   log1 = "/var/log1",
>   log2 = "/var/log2"
> 
> }
> 
> Now... when I try to do the following:
> 
> string subDirectory = "example";
> 
> string newPath = buildPath(path.log1, subDirectory);
> 
> I get the following errors:
> 
> Error: template std.path.buildPath does not match any function template
> declaration
> Error: template std.path.buildPath(C) if (isSomeChar!(C)) cannot deduce
> template function from argument types !()(path,string)
> Error: template std.path.buildPath does not match any function template
> declaration
> Error: template std.path.buildPath(C) if (isSomeChar!(C)) cannot deduce
> template function from argument types !()(path,string)
> 
> Is this a bug in std.path.buildPath() or is there anything I'm doing wrong?
> 

A bug, as an enum member is supposed to implicitly convert to its base type. [1]

You might be able to work-around it like this

   template _path() {
      enum : string {
        log1 = "/var/log1",
        log2 = "/var/log2"
      }
   }
   alias _path!() path;

artur

[1] Actually, D's "typesafe variadic functions" don't play well with certain other features too, eg

   void f(A...)(A a) {}
   void f()(string[] a...) {}
   f("a", "b"); // expecting the second overload to be called is reasonable,
                // but this isn't what's going to happen.

Top | Discussion index | About this forum | D home