Comment #1 by razvan.nitu1305 — 2017-03-28T07:42:32Z
I think we're in a dilemma here since whatever choice we make there will be inconsistencies. Nullable's get should throw (and it does) when you try to fetch the value (1); on the other hand, formattedWrite should print nulls (2) but when it tries to fetch the nullable (by calling get) an exception is thrown due to statement (1). As I see it, there are 2 possibilities: either we make Nullable's
get method return null if the value is unassigned or we specialize formattedWrite for Nullable's (which is not a valid measure). In my opinion, it should be on the user's account to check if the Nullable is assigned before printing it, thus making this error a user error.
Comment #2 by chalucha — 2017-03-28T08:15:32Z
It's easy to handle this with just one value to print, but when it is used in some more complex structure for example just for the simple debugging purposes, it becames PITA to workaround it while otherwise all fields of the structure are printed just fine.
Nullable.get can't return null as it is meant to return the value type. For example Nullable!int(42).get can't return null.
So in my opinion only specialized formattedWrite can be considered.
For example in C# this is not the problem: http://www.tutorialspoint.com/csharp/csharp_nullables.htm
I think that Nullable should be as user friendly as it is possible. See for example issue #13017 which was finally fixed recently.
Comment #3 by chalucha — 2017-03-28T08:19:44Z
One more thing.
Nullable!int foo;
writefln("%s", foo);
outputs Nullable.null
So it is at least inconsistent here.
Comment #4 by andre — 2017-06-15T16:56:15Z
This issue is also reproducible with std.conv: text
import std.conv: text;
import std.typecons;
struct Foo
{
Nullable!string bar;
}
void main()
{
string s = Foo().text;
}
Comment #5 by cromfr — 2017-10-19T17:05:53Z
struct TestInt
{
Nullable!int value;
}
writeln(TestInt());//Print: Nullable.null
struct TestString
{
Nullable!string value;
}
writeln(TestString());//Raise exception
Nullable!string is implicitly convertible to a string, thus calling the following std.format.formatElement overloading:
```
void formatElement(Writer, T, Char)(auto ref Writer w, T val, const ref FormatSpec!Char f)
if (is(StringTypeOf!T) && !is(T == enum))
```
that generates the exception when trying to store the string value in a variable here: https://github.com/dlang/phobos/blob/05e65e6086d8d5ebdd1b95350cb6a79a1198e7d0/std/format.d#L3072
The correct called overloading should be:
```
void formatElement(Writer, T, Char)(auto ref Writer w, auto ref T val, const ref FormatSpec!Char f)
if (!is(StringTypeOf!T) && !is(CharTypeOf!T) || is(T == enum))
```
that forwards to a formatValue call.
I am currently working on a pull request
Comment #6 by bugzilla — 2019-12-07T13:53:29Z
*** Issue 19435 has been marked as a duplicate of this issue. ***
Comment #7 by schveiguy — 2020-01-10T18:25:45Z
Ran into this today. I may work on a PR to fix it. Any ideas if this is in progress?
Very annoying when it happens, especially when you print a Nullable!string directly, it works.
@CromFr updated dlang/phobos pull request #5797 "Issue 17269: formattedWrite of struct with Nullable value fails" fixing this issue:
- Fix Issue 17269 - Use toString if available instead of implicitly converting to string
- Add code from issue 17269 as unittest
https://github.com/dlang/phobos/pull/5797
Comment #10 by dlang-bot — 2021-02-05T11:01:33Z
dlang/phobos pull request #5797 "Issue 17269: formattedWrite of struct with Nullable value fails" was merged into master:
- f1ff0097abd10bb420e61920fcc4efb0d678a0a7 by Crom (Thibaut CHARLES):
Fix Issue 17269 - Use toString if available instead of implicitly converting to string
- 06689a6b506ea25f6388bfc8cccea4a6ec050ee3 by Sebastian Wilzbach:
Add code from issue 17269 as unittest
https://github.com/dlang/phobos/pull/5797