diff --git a/std/container/rbtree.d b/std/container/rbtree.d index 2568af1f0..108a085ff 100644 --- a/std/container/rbtree.d +++ b/std/container/rbtree.d @@ -1710,13 +1710,18 @@ assert(equal(rbt[], [5])); } /** - Formats the RedBlackTree into a sink function. For more info see - $(D std.format.formatValue) - */ - void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const { - sink("RedBlackTree("); - sink.formatValue(this[], fmt); - sink(")"); + Formats the RedBlackTree into a sink function. For more info see $(D + std.format.formatValue). Note that this only is available when the + element type can be formatted. Otherwise, the default toString from + Object is used. + */ + static if(is(typeof((){FormatSpec!(char) fmt; formatValue((const(char)[]) {}, ConstRange.init, fmt);}))) + { + void toString(scope void delegate(const(char)[]) sink, FormatSpec!char fmt) const { + sink("RedBlackTree("); + sink.formatValue(this[], fmt); + sink(")"); + } } /** @@ -2044,3 +2049,10 @@ unittest import std.algorithm : equal; assert(rt1.upperBound(2).equal([3, 4, 5])); } + +// issue 15941 +unittest +{ + class C {} + RedBlackTree!(C, "cast(void*)a < cast(void*)b") tree; +} diff --git a/std/getopt.d b/std/getopt.d index 594c9faea..3e04b4540 100644 --- a/std/getopt.d +++ b/std/getopt.d @@ -530,7 +530,7 @@ follow this pattern: [config override], option, [description], receiver, - config override: a config value, optional - - option: a string + - option: a string or a char - description: a string, optional - receiver: a pointer or a callable */ @@ -541,6 +541,7 @@ private template optionValidator(A...) enum fmt = "getopt validator: %s (at position %d)"; enum isReceiver(T) = isPointer!T || (is(T==function)) || (is(T==delegate)); + enum isOptionStr(T) = isSomeString!T || isSomeChar!T; auto validator() { @@ -551,24 +552,24 @@ private template optionValidator(A...) { msg = format(fmt, "first argument must be a string or a config", 0); } - else static if (!isSomeString!(A[0]) && !is(A[0] == config)) + else static if (!isOptionStr!(A[0]) && !is(A[0] == config)) { - msg = format(fmt, "invalid argument type " ~ A[0].stringof, 0); + msg = format(fmt, "invalid argument type: " ~ A[0].stringof, 0); } else foreach (i; staticIota!(1, A.length)) { - static if (!isReceiver!(A[i]) && !isSomeString!(A[i]) && + static if (!isReceiver!(A[i]) && !isOptionStr!(A[i]) && !(is(A[i] == config))) { - msg = format(fmt, "invalid argument type " ~ A[i].stringof, i); + msg = format(fmt, "invalid argument type: " ~ A[i].stringof, i); break; } - else static if (isReceiver!(A[i]) && !isSomeString!(A[i-1])) + else static if (isReceiver!(A[i]) && !isOptionStr!(A[i-1])) { msg = format(fmt, "a receiver can not be preceeded by a receiver", i); break; } - else static if (i > 1 && isSomeString!(A[i]) && isSomeString!(A[i-1]) + else static if (i > 1 && isOptionStr!(A[i]) && isOptionStr!(A[i-1]) && isSomeString!(A[i-2])) { msg = format(fmt, "a string can not be preceeded by two strings", i); @@ -591,12 +592,31 @@ private template optionValidator(A...) { alias P = void*; alias S = string; + alias A = char; alias C = config; alias F = void function(); + static assert(optionValidator!(S,P) == ""); + static assert(optionValidator!(S,F) == ""); + static assert(optionValidator!(A,P) == ""); + static assert(optionValidator!(A,F) == ""); + + static assert(optionValidator!(C,S,P) == ""); + static assert(optionValidator!(C,S,F) == ""); + static assert(optionValidator!(C,A,P) == ""); + static assert(optionValidator!(C,A,F) == ""); + + static assert(optionValidator!(C,S,S,P) == ""); + static assert(optionValidator!(C,S,S,F) == ""); + static assert(optionValidator!(C,A,S,P) == ""); + static assert(optionValidator!(C,A,S,F) == ""); + static assert(optionValidator!(C,S,S,P) == ""); static assert(optionValidator!(C,S,S,P,C,S,F) == ""); - static assert(optionValidator!(C,S,S,P,C,S,F) == ""); + static assert(optionValidator!(C,S,P,C,S,S,F) == ""); + + static assert(optionValidator!(C,A,P,A,S,F) == ""); + static assert(optionValidator!(C,A,P,C,A,S,F) == ""); static assert(optionValidator!(P,S,S) != ""); static assert(optionValidator!(P,P,S) != ""); @@ -605,6 +625,29 @@ private template optionValidator(A...) static assert(optionValidator!(S,S,P,S,S,P,S) != ""); static assert(optionValidator!(S,S,P,P) != ""); static assert(optionValidator!(S,S,S,P) != ""); + + static assert(optionValidator!(C,A,S,P,C,A,F) == ""); + static assert(optionValidator!(C,A,P,C,A,S,F) == ""); +} + +unittest // bugzilla 15914 +{ + bool opt; + string[] args = ["program", "-a"]; + getopt(args, config.passThrough, 'a', &opt); + assert(opt); + opt = false; + args = ["program", "-a"]; + getopt(args, 'a', &opt); + assert(opt); + opt = false; + args = ["program", "-a"]; + getopt(args, 'a', "help string", &opt); + assert(opt); + opt = false; + args = ["program", "-a"]; + getopt(args, config.caseSensitive, 'a', "help string", &opt); + assert(opt); } private void getoptImpl(T...)(ref string[] args, ref configuration cfg,