@@ -1865,46 +1865,60 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
1865
1865
auto ref matchImpl (SumTypes... )(auto ref SumTypes args)
1866
1866
if (allSatisfy! (isSumType, SumTypes) && args.length > 0 )
1867
1867
{
1868
- alias typeCounts = Map! (typeCount, SumTypes);
1869
- alias stride (size_t i) = .stride! (i, typeCounts);
1870
- alias TagTuple = .TagTuple! typeCounts;
1868
+ // Single dispatch (fast path)
1869
+ static if (args.length == 1 )
1870
+ {
1871
+ /* When there's only one argument, the caseId is just that
1872
+ * argument's tag, so there's no need for TagTuple.
1873
+ */
1874
+ enum handlerArgs (size_t caseId) =
1875
+ " args[0].get!(SumTypes[0].Types[" ~ toCtString! caseId ~ " ])()" ;
1871
1876
1872
- alias handlerArgs (size_t caseId) = .handlerArgs! (caseId, typeCounts);
1877
+ alias valueTypes (size_t caseId) =
1878
+ typeof (args[0 ].get ! (SumTypes[0 ].Types[caseId])());
1873
1879
1874
- /* An AliasSeq of the types of the member values in the argument list
1875
- * returned by `handlerArgs!caseId`.
1876
- *
1877
- * Note that these are the actual (that is, qualified) types of the
1878
- * member values, which may not be the same as the types listed in
1879
- * the arguments' `.Types` properties.
1880
- */
1881
- template valueTypes (size_t caseId)
1880
+ enum numCases = SumTypes[0 ].Types.length;
1881
+ }
1882
+ // Multiple dispatch (slow path)
1883
+ else
1882
1884
{
1883
- enum tags = TagTuple.fromCaseId(caseId);
1885
+ alias typeCounts = Map! (typeCount, SumTypes);
1886
+ alias stride (size_t i) = .stride! (i, typeCounts);
1887
+ alias TagTuple = .TagTuple! typeCounts;
1884
1888
1885
- template getType (size_t i)
1889
+ alias handlerArgs (size_t caseId) = .handlerArgs! (caseId, typeCounts);
1890
+
1891
+ /* An AliasSeq of the types of the member values in the argument list
1892
+ * returned by `handlerArgs!caseId`.
1893
+ *
1894
+ * Note that these are the actual (that is, qualified) types of the
1895
+ * member values, which may not be the same as the types listed in
1896
+ * the arguments' `.Types` properties.
1897
+ */
1898
+ template valueTypes (size_t caseId)
1886
1899
{
1887
- enum tid = tags[i];
1888
- alias T = SumTypes[i].Types[tid];
1889
- alias getType = typeof (args[i].get ! T());
1900
+ enum tags = TagTuple.fromCaseId(caseId);
1901
+
1902
+ template getType (size_t i)
1903
+ {
1904
+ enum tid = tags[i];
1905
+ alias T = SumTypes[i].Types[tid];
1906
+ alias getType = typeof (args[i].get ! T());
1907
+ }
1908
+
1909
+ alias valueTypes = Map! (getType, Iota! (tags.length));
1890
1910
}
1891
1911
1892
- alias valueTypes = Map! (getType, Iota! (tags.length));
1912
+ /* The total number of cases is
1913
+ *
1914
+ * Π SumTypes[i].Types.length for 0 ≤ i < SumTypes.length
1915
+ *
1916
+ * Conveniently, this is equal to stride!(SumTypes.length), so we can
1917
+ * use that function to compute it.
1918
+ */
1919
+ enum numCases = stride! (SumTypes.length);
1893
1920
}
1894
1921
1895
- /* The total number of cases is
1896
- *
1897
- * Π SumTypes[i].Types.length for 0 ≤ i < SumTypes.length
1898
- *
1899
- * Or, equivalently,
1900
- *
1901
- * ubyte[SumTypes[0].Types.length]...[SumTypes[$-1].Types.length].sizeof
1902
- *
1903
- * Conveniently, this is equal to stride!(SumTypes.length), so we can
1904
- * use that function to compute it.
1905
- */
1906
- enum numCases = stride! (SumTypes.length);
1907
-
1908
1922
/* Guaranteed to never be a valid handler index, since
1909
1923
* handlers.length <= size_t.max.
1910
1924
*/
@@ -1961,7 +1975,12 @@ private template matchImpl(Flag!"exhaustive" exhaustive, handlers...)
1961
1975
mixin (" alias " , handlerName! hid, " = handler;" );
1962
1976
}
1963
1977
1964
- immutable argsId = TagTuple(args).toCaseId;
1978
+ // Single dispatch (fast path)
1979
+ static if (args.length == 1 )
1980
+ immutable argsId = args[0 ].tag;
1981
+ // Multiple dispatch (slow path)
1982
+ else
1983
+ immutable argsId = TagTuple(args).toCaseId;
1965
1984
1966
1985
final switch (argsId)
1967
1986
{
0 commit comments