www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - error : outer function context of `D main` is needed to `new` nested

reply Bert <Bert gmail.com> writes:
void main()
{
     class X { ... }
     auto f = foo!X;
}

then in another module I have a templated function foo that 
simply new's x:

auto foo(T)() { return new T; }

yet I get the error.

I realize that X is local to main and I realize I could do 
something like

foo(new X);

but that completely defeats the purpose(my context is more 
complicated). I need to construct X, not have the user do it.

I thought the templated function would be instantiated at the 
call site?

I've tried to "hack" it in various ways but nothing works. I've 
imported the model, but since X is local to main it can't be 
seen. I've tried to fully qualify it but it can't be found. 
main.main.X says something about void(the return type of main()): 
no property `` for type `void`.

template foo(T)
{
	alias foo = T;
         alias foo = () { return new T; }; // or
}

then I can do new foo!T, but I cannot actually construct T like I 
need to. I cannot seem to return a proper type either. I've tried 
returning a lambda and so on, but D is enforcing the type be 
accessible even if the function will be used in the correct 
context.

I don't understand stand why it is a problem when the template 
functions are suppose to be instantiated at the call site.

Seems like a complete pain just to be able to construct a type 
outside it's context(but the construction is totally within the 
context, or should be. I'm simply trying to provide a simple 
wrapper that does some boilerplate and makes everything look 
nice).
Aug 14 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Thursday, 15 August 2019 at 01:55:17 UTC, Bert wrote:
 void main()
 {
     class X { ... }
I would just make it `static class X` and then it shoudl work fine. Won't be able to access main's local variables then though, but you could pass the necessary ones through the constructors or something.
Aug 14 2019
parent Bert <Bert gmail.com> writes:
On Thursday, 15 August 2019 at 02:23:06 UTC, Adam D. Ruppe wrote:
 On Thursday, 15 August 2019 at 01:55:17 UTC, Bert wrote:
 void main()
 {
     class X { ... }
I would just make it `static class X` and then it should work fine. Won't be able to access main's local variables then though, but you could pass the necessary ones through the constructors or something.
That might work, I can't think of the case where I would need to access them, although some could exist. It's not a general solution though. I've came up with a work around that isn't great but seems to work. So the whole point of this is that the class cannot be constructed because a context pointer won't exist outside of main? It seems that things were done backwards, the class never references anything outside it and for all practical purposes is static... seems that all classes should have been default static and something like `nonstatic class` should have been required to capture the context. Or better yet, some way to construct the class if is effectively a static class to get most use cases and error else rather than just scrub all possibilities. e.g., maybe there could be a way to construct the class manually(emplace?) and just use a null context pointer and hope for the best or somehow figure out if it requires a context and if so then error? If the outer context can be captured by the function, then it could be passed to emplace. For example, one could pass a delegate and use it's context pointer, and as long as it is the same as the context the class is defined in, then it should be used? I am using emplace now to construct the class and it seems to work without the error but, of course, the context will be wrong. Is there any way to somehow get the context properly? (since these things are relatively fixed in code so should the context and one should be able to statically reference it with the appropriate symbol?) So basically I can essentially do what I said above with emplace but this is error prone without a proper context. I assume that when a class is defined, the outer is always the context of where the class is defined and not where it is created. If this is true, and it should be since it would make no real since other wise(unless one was very careful) then one would be able to reference that context statically. e.g., X.Context should return the context for the class X. I haven't been able to figure out how to do this though and I will just rely on my original workaround for now since it is safe.
Aug 16 2019