Emplace using private constructor

Ali Çehreli acehreli at yahoo.com
Fri Jun 7 09:14:24 PDT 2013


tldr; I had the crazy idea of mixing-in a specialization of emplace but 
failed probably because mixin does not respect template constraints.

On 06/07/2013 06:50 AM, develop32 wrote:

 > Nevermind, problem was not worth the question. I just copied code from
 > Phobos std.conv.emplace and placed it directly in my code, it works
 > since it is in the same module as the private constructor.

But it is too heavy-handed. Your problem exposes a real weakness. Other 
library code will make assumptions like emplace does below and they will 
fail if the constructor is not accessible. From std.conv.emplace:

     // Call the ctor if any
     static if (is(typeof(result.__ctor(args))))
     {
         // T defines a genuine constructor accepting args
         // Go the classic route: write .init first, then call ctor
         result.__ctor(args);
     }

I tried making your code better but not copying emplace's implementation:

module display;

import std.conv;

class Display
{
private:
     const string name;

     this(string name)
     {
         this.name = name;
     }

public:

     static Display emplace(Args...)(void[] chunk, auto ref Args args)
     {
         return std.conv.emplace!(Display)(chunk, args);
     }
}

Here is a test program:

import display;

void main()
{
     enum roomNeeded = __traits(classInstanceSize, Display);
     ubyte[roomNeeded] buffer;
     auto d = Display.emplace(buffer, "hello");
}

But I failed with the same error:

Error: static assert  "Don't know how to initialize an object of type 
Display with arguments (string)"

Then I thought about mixing in the template but that did not work either:

class Display
{
// ...

     static Display emplace(Args...)(void[] chunk, auto ref Args args)
     {
         mixin std.conv.emplace!(Display, string);
     }
}

The error message indicated that mixin was picking the wrong 
specialization, because it had a template constraint for 'struct':

T* emplace(T, Args...)(T* chunk, auto ref Args args)
     if (is(T == struct))
{
     // ...
}

If it picked the one that matched is(T == class) then we would have 
achieved our goal without copy-pasting.

Still, if it worked, it also feels hacky because we would be mixing-in a 
specialization right inside our function and hope that it would somehow 
work in our environment. For example, the specialization of emplace has 
a return statement:

     return result;

What if my function should not return? I guess then we would mix-in 
inside a wrapper function, call that function, and ignore the return value.

I have a feeling that bearophile already has a bug report about all of 
this but I haven't checked yet. :p

Not the same, but it look like it is related to this bug:

   http://d.puremagic.com/issues/show_bug.cgi?id=9235

Ali



More information about the Digitalmars-d-learn mailing list