Thread overview | ||||||
---|---|---|---|---|---|---|
|
May 03, 2012 How to prevent direct public creation of a struct? | ||||
---|---|---|---|---|
| ||||
I want to do something like this: ------------------------------------------ module moduleFoo; // Only allow certain values of "str" template foo(string str) { static assert(str == "a" || str == "b" || str == "c"); immutable foo = Foo(str); } struct Foo { // Only "a", "b", and "c" should be allowed, // checked at compile-time via "template foo". // Also, not modifyable. private string _str; @property string str() { return _str; } } ------------------------------------------ I want struct Foo itself to be public, but I want to *force* all code outside moduleFoo to *create* Foo via the "foo" template. Copying should be allowed though. Ie: ------------------------------------------ auto a = foo!"a"; // ok a.str = "b"; // Error: str is a read-only property auto z = foo!"z"; // Error: fails static assert auto a2 = a; // Copy it: ok auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" Foo x; // Kinda ambivalent about this: I'd prefer if it were disallowed, but I don't think that's possible. If it's indeed impossible, I know I can just declare Foo.str as (string str = "a";) so that's not a big problem. ------------------------------------------ The *key* thing here that I'm not sure how to do is: How do I disallow this?: auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" |
May 03, 2012 Re: How to prevent direct public creation of a struct? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Thursday, 3 May 2012 at 21:36:53 UTC, Nick Sabalausky wrote:
> I want to do something like this:
>
> ------------------------------------------
> module moduleFoo;
>
> // Only allow certain values of "str"
> template foo(string str)
> {
> static assert(str == "a" || str == "b" || str == "c");
> immutable foo = Foo(str);
> }
>
> struct Foo
> {
> // Only "a", "b", and "c" should be allowed,
> // checked at compile-time via "template foo".
> // Also, not modifyable.
> private string _str;
> @property string str()
> {
> return _str;
> }
> }
> ------------------------------------------
>
> I want struct Foo itself to be public, but I want to *force* all code
> outside moduleFoo to *create* Foo via the "foo" template. Copying should be
> allowed though. Ie:
>
> ------------------------------------------
> auto a = foo!"a"; // ok
> a.str = "b"; // Error: str is a read-only property
> auto z = foo!"z"; // Error: fails static assert
> auto a2 = a; // Copy it: ok
>
> auto b = Foo("b"); // Error: I want to *force* the usage of "template foo"
>
> Foo x; // Kinda ambivalent about this: I'd prefer if it were disallowed, but
> I don't think that's possible. If it's indeed impossible, I know I can just
> declare Foo.str as (string str = "a";) so that's not a big problem.
> ------------------------------------------
>
> The *key* thing here that I'm not sure how to do is: How do I disallow
> this?:
>
> auto b = Foo("b"); // Error: I want to *force* the usage of "template foo"
I would have thought adding a private this(string str) constructor would work but then foo can't be called from a separate module ("privcons.d(5): Error: struct privcons.Foo member this is not accessible" which is the same but desirable error it gives if you do "auto b = Foo("b");"). I thought all module members had access to private members of the same module but I guess that's not the case with template functions.
|
May 03, 2012 Re: How to prevent direct public creation of a struct? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nick Sabalausky | On Thu, 03 May 2012 17:37:47 -0400, Nick Sabalausky wrote:
> The *key* thing here that I'm not sure how to do is: How do I disallow this?:
>
> auto b = Foo("b"); // Error: I want to *force* the usage of "template
> foo"
The @disable annotation can do this, I believe:
struct Foo
{
@disable this(); // Cannot use default constructor
}
But this disables it for code within the module as well as outside, so you may wish to also add a private constructor.
|
May 04, 2012 Re: How to prevent direct public creation of a struct? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Anderson | "Brad Anderson" <eco@gnuk.net> wrote in message news:jhsccvjskiqqzzqbdugx@forum.dlang.org... > On Thursday, 3 May 2012 at 21:36:53 UTC, Nick Sabalausky wrote: >> I want to do something like this: >> >> ------------------------------------------ >> module moduleFoo; >> >> // Only allow certain values of "str" >> template foo(string str) >> { >> static assert(str == "a" || str == "b" || str == "c"); >> immutable foo = Foo(str); >> } >> >> struct Foo >> { >> // Only "a", "b", and "c" should be allowed, >> // checked at compile-time via "template foo". >> // Also, not modifyable. >> private string _str; >> @property string str() >> { >> return _str; >> } >> } >> ------------------------------------------ >> >> I want struct Foo itself to be public, but I want to *force* all code >> outside moduleFoo to *create* Foo via the "foo" template. Copying should >> be >> allowed though. Ie: >> >> ------------------------------------------ >> auto a = foo!"a"; // ok >> a.str = "b"; // Error: str is a read-only property >> auto z = foo!"z"; // Error: fails static assert >> auto a2 = a; // Copy it: ok >> >> auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" >> >> Foo x; // Kinda ambivalent about this: I'd prefer if it were disallowed, >> but >> I don't think that's possible. If it's indeed impossible, I know I can >> just >> declare Foo.str as (string str = "a";) so that's not a big problem. >> ------------------------------------------ >> >> The *key* thing here that I'm not sure how to do is: How do I disallow this?: >> >> auto b = Foo("b"); // Error: I want to *force* the usage of "template foo" > > I would have thought adding a private this(string str) constructor would work but then foo can't be called from a separate module ("privcons.d(5): Error: struct privcons.Foo member this is not accessible" which is the same but desirable error it gives if you do "auto b = Foo("b");"). I thought all module members had access to private members of the same module but I guess that's not the case with template functions. Hmm, interestingly, it works if the template calls through an intermediary private function: http://d.puremagic.com/issues/show_bug.cgi?id=8028 I don't know if I'm relying on a bug or working around a bug, but this seems to work, *and* disallows "Foo b;" which is nice: --------------------------------------------------- template foo(string str) { static assert(["a", "b", "c"].find(str), "Invalid str: '"~str~"'"); immutable foo = _foo(name); } private Foo _foo(string str) { return Foo(str); } struct Foo { immutable string str; private this(string str) { this.str = str; } @disable this(); } --------------------------------------------------- // In a serparate module: Foo a = foo!"a"; // Ok auto a2 = a; // Ok a.str = "b"; // Error: can only initialize const member name inside constructor auto z = foo!"z"; // Error: static assert "Invalid str: 'z'" instantiated from here: foo!("z") auto b = Foo("b"); // Error: struct test2.Foo member this is not accessible Foo x; // Error: variable test1.main.x initializer required for type Foo --------------------------------------------------- So that's awesome, everything as I wanted :) |
Copyright © 1999-2021 by the D Language Foundation