www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - public alias to private template implementation

reply "monarch_dodra" <monarchdodra gmail.com> writes:
Reduced:

//----
module A;

alias fun = Impl!int;

private template Impl(T)
{
     void Impl(){}
}
//----
void main()
{
     fun();
}
//----
Error: function A.Impl!int.Impl is not accessible from module main
//----

I'm trying to implement a set of public funtions, in terms of a 
template. Said template has no business being know to the user, 
so I want to mark it as private. Unfortunately, if I do this, 
then I can't use the alias, because "Impl is private".

Question 1: Is this the correct behavior? I'd have expected that 
if my alias is public, it would allow any one from outside to 
make the call correctly.

Question 2: Is there a "correct" way to do this? I possible, I'd 
want to avoid "nesting" the template, eg:
auto fun(){return Impl!int();}
As that would:
a) require more typing ^^
b) incur an extra function call in non-inline
c) if at all possible, I actually need "fun" to be a template, so 
that it can be inlined.
Sep 16 2013
next sibling parent reply "Meta" <jared771 gmail.com> writes:
On Monday, 16 September 2013 at 21:00:21 UTC, monarch_dodra wrote:
 I'm trying to implement a set of public funtions, in terms of a 
 template. Said template has no business being know to the user, 
 so I want to mark it as private. Unfortunately, if I do this, 
 then I can't use the alias, because "Impl is private".

 Question 1: Is this the correct behavior? I'd have expected 
 that if my alias is public, it would allow any one from outside 
 to make the call correctly.

 Question 2: Is there a "correct" way to do this? I possible, 
 I'd want to avoid "nesting" the template, eg:
 auto fun(){return Impl!int();}
 As that would:
 a) require more typing ^^
 b) incur an extra function call in non-inline
 c) if at all possible, I actually need "fun" to be a template, 
 so that it can be inlined.
It makes sense to me, and seems like it would be analogous to returning a private member from a public method in structs or classes. However, since an alias rewritten to what it is aliased to (they completely disappear at compile time), I think your code would be equivalent to this: //---- module A; private template Impl(T) { void Impl(){} } //---- module B; //I'm assuming that main is supposed to be in a different module? import A; void main() { Impl!int(); } So you're really directly accessing a private symbol. Perhaps a workaround could be something like this: //---- module Test; static const fun = &Impl!int; private template Impl(T) { void Impl(){} } //---- module main; import Test; void main() { fun(); } I had to do fun = &Impl!int because the compiler complained about fun = Impl!int.
Sep 16 2013
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Monday, 16 September 2013 at 23:53:14 UTC, Meta wrote:
 So you're really directly accessing a private symbol. Perhaps a 
 workaround could be something like this:

 //----
 module Test;
 static const fun = &Impl!int;
 private template Impl(T)
 {
     void Impl(){}
 }

 //----
 module main;
 import Test;
 void main()
 {
     fun();
 }

 I had to do fun = &Impl!int because the compiler complained 
 about fun = Impl!int.
This seems to be not working, because Impl actually holds an overload. It's actually something like: private template Impl(T) { void Impl(){} void Impl(int){} } Grown.
Sep 16 2013
prev sibling next sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 16/09/13 23:00, monarch_dodra wrote:
 Question 1: Is this the correct behavior? I'd have expected that if my alias is
 public, it would allow any one from outside to make the call correctly.
See: http://d.puremagic.com/issues/show_bug.cgi?id=10996
 Question 2: Is there a "correct" way to do this? I possible, I'd want to avoid
 "nesting" the template, eg:
 auto fun(){return Impl!int();}
 As that would:
 a) require more typing ^^
 b) incur an extra function call in non-inline
 c) if at all possible, I actually need "fun" to be a template, so that it can
be
 inlined.
Indeed, I used that workaround of manually nesting the functions in some code of mine: https://github.com/WebDrake/Dgraph/blob/master/dgraph/graph.d#L492-L516 ... but that's not a general solution, I was able to tolerate it because it's a limited and predictable set of instructions. Jacob Carlborg suggested using opDispatch (cf. how it's done in Proxy), which should automate the "nesting" of template functions. I avoided it simply because in my case I thought that doing it manually would be less hassle than getting opDispatch set up to cover every possible case, but depending on your use case it might be the better option.
Sep 17 2013
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Tuesday, 17 September 2013 at 08:47:25 UTC, Joseph Rushton 
Wakeling wrote:
 On 16/09/13 23:00, monarch_dodra wrote:
 Question 1: Is this the correct behavior? I'd have expected 
 that if my alias is
 public, it would allow any one from outside to make the call 
 correctly.
See: http://d.puremagic.com/issues/show_bug.cgi?id=10996
 Question 2: Is there a "correct" way to do this? I possible, 
 I'd want to avoid
 "nesting" the template, eg:
 auto fun(){return Impl!int();}
 As that would:
 a) require more typing ^^
 b) incur an extra function call in non-inline
 c) if at all possible, I actually need "fun" to be a template, 
 so that it can be
 inlined.
Indeed, I used that workaround of manually nesting the functions in some code of mine: https://github.com/WebDrake/Dgraph/blob/master/dgraph/graph.d#L492-L516 ... but that's not a general solution, I was able to tolerate it because it's a limited and predictable set of instructions. Jacob Carlborg suggested using opDispatch (cf. how it's done in Proxy), which should automate the "nesting" of template functions. I avoided it simply because in my case I thought that doing it manually would be less hassle than getting opDispatch set up to cover every possible case, but depending on your use case it might be the better option.
Thanks. I'm not very fluent with opDispatch though. Doesn't that only work if you have an struct/class instance though? My "fun" is a free frunction. I you are able to adapt it to my trivial usecase, it might be clearer to me what you have in mind.
Sep 17 2013
parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 17/09/13 11:30, monarch_dodra wrote:
 Thanks. I'm not very fluent with opDispatch though. Doesn't that only work if
 you have an struct/class instance though? My "fun" is a free frunction.
Ack. Sorry, I overlooked that. :-( Still, I think this provides greater impulse for Issue 10996 to be fixed, since your issue clearly stems from the same access implementation issues. If you make a public alias, you'd expect public members of whatever you're aliasing to be public through that alias. I guess it might be desirable to require some clear indication "Yes, I really, really know what I'm doing and I do want this alias to be public" -- e.g. compelling you to use the public keyword explicitly.
Sep 17 2013
prev sibling parent "Dicebot" <public dicebot.lv> writes:
That is actually very weird because you can override protection 
attribute with alias for an aggregate:

// b.d
private struct A_
{
}

public alias A = A_;

// a.d
void main() { A a; } // fine!

That inconsistency feels plain wrong. Worth enhancement request 
at least.
Sep 17 2013